CountryInfoGetter::GetRegionInfo - extended country information (name, flag, ...)

This commit is contained in:
vng 2012-01-26 12:33:38 +03:00 committed by Alex Zolotarev
parent 97f58f98a4
commit d960e0e43f
9 changed files with 129 additions and 70 deletions

View file

@ -261,12 +261,14 @@ string IntermediateResult::DebugPrint() const
string IntermediateResult::RegionInfo::GetRegion(storage::CountryInfoGetter const * pInfo) const
{
storage::CountryInfo info;
if (!m_file.empty())
return pInfo->GetRegionName(m_file);
pInfo->GetRegionInfo(m_file, info);
else if (m_valid)
return pInfo->GetRegionName(m_point);
else
return string();
pInfo->GetRegionInfo(m_point, info);
return info.m_name;
}
} // namespace search::impl

View file

@ -142,24 +142,45 @@ namespace
}
};
class DoStoreFile2Name
class DoStoreFile2Info
{
map<string, string> & m_file2name;
public:
DoStoreFile2Name(map<string, string> & file2name) : m_file2name(file2name) {}
map<string, CountryInfo> & m_file2info;
string m_lastFlag;
void operator() (string name, string const & file, string const &,
public:
DoStoreFile2Info(map<string, CountryInfo> & file2info) : m_file2info(file2info) {}
void operator() (string name, string file, string const & flag,
uint32_t size, int64_t, int)
{
// if 'file' is empty - it's equal to name
if (size && !file.empty())
{
size_t const i = file.find_first_of('_');
if (i != string::npos)
name = file.substr(0, i) + '_' + name;
if (!flag.empty())
m_lastFlag = flag;
if (name != file)
m_file2name[file] = name;
if (size)
{
CountryInfo info;
// if 'file' is empty - it's equal to 'name'
if (!file.empty())
{
// make compound name: country_region
size_t const i = file.find_first_of('_');
if (i != string::npos)
name = file.substr(0, i) + '_' + name;
// fill 'name' only when it differs with 'file'
if (name != file)
info.m_name.swap(name);
}
else
file.swap(name);
// Do not use 'name' here! It was swapped!
ASSERT ( !m_lastFlag.empty(), () );
info.m_flag = m_lastFlag;
m_file2info[file] = info;
}
}
};
@ -185,10 +206,10 @@ int64_t LoadCountries(string const & jsonBuffer, CountriesContainerT & countries
return LoadCountriesImpl(jsonBuffer, doStore);
}
void LoadCountryFile2Name(string const & jsonBuffer, map<string, string> & id2name)
void LoadCountryFile2CountryInfo(string const & jsonBuffer, map<string, CountryInfo> & id2info)
{
ASSERT ( id2name.empty(), () );
DoStoreFile2Name doStore(id2name);
ASSERT ( id2info.empty(), () );
DoStoreFile2Info doStore(id2info);
LoadCountriesImpl(jsonBuffer, doStore);
}

View file

@ -1,6 +1,7 @@
#pragma once
#include "simple_tree.hpp"
#include "country_decl.hpp"
#include "../defines.hpp"
@ -40,7 +41,7 @@ namespace storage
class Country
{
friend class update::SizeUpdater;
/// Name in the coutry node tree
/// Name in the country node tree
string m_name;
/// Flag to display
string m_flag;
@ -70,7 +71,7 @@ namespace storage
/// @return version of country file or -1 if error was encountered
int64_t LoadCountries(string const & jsonBuffer, CountriesContainerT & countries);
void LoadCountryFile2Name(string const & jsonBuffer, map<string, string> & id2name);
void LoadCountryFile2CountryInfo(string const & jsonBuffer, map<string, CountryInfo> & id2info);
void LoadCountryCode2File(string const & jsonBuffer, multimap<string, string> & code2file);
bool SaveCountries(int64_t version, CountriesContainerT const & countries, string & jsonBuffer);

33
storage/country_decl.hpp Normal file
View file

@ -0,0 +1,33 @@
#pragma once
#include "../geometry/rect2d.hpp"
#include "../std/string.hpp"
namespace storage
{
struct CountryDef
{
string m_name;
m2::RectD m_rect;
CountryDef() {}
CountryDef(string const & name, m2::RectD const & r)
: m_name(name), m_rect(r)
{
}
};
struct CountryInfo
{
/// Name (in native language) of country or region.
/// (if empty - equals to file name of country - no additional memory)
string m_name;
/// Flag of country or region.
string m_flag;
bool IsNotEmpty() const { return !m_flag.empty(); }
};
}

View file

@ -1,4 +1,5 @@
#include "country_info.hpp"
#include "country_polygon.hpp"
#include "country.hpp"
#include "../indexer/geometry_serialization.hpp"
@ -20,7 +21,7 @@ namespace storage
string buffer;
countryR.ReadAsString(buffer);
LoadCountryFile2Name(buffer, m_id2name);
LoadCountryFile2CountryInfo(buffer, m_id2info);
}
template <class ToDo>
@ -85,38 +86,33 @@ namespace storage
return string();
}
string CountryInfoGetter::GetRegionName(m2::PointD const & pt) const
void CountryInfoGetter::GetRegionInfo(m2::PointD const & pt, CountryInfo & info) const
{
GetByPoint doGet(*this, pt);
ForEachCountry(pt, doGet);
if (doGet.m_res != -1)
return GetRegionName(m_countries[doGet.m_res].m_name);
return string();
GetRegionInfo(m_countries[doGet.m_res].m_name, info);
}
string CountryInfoGetter::GetRegionName(string const & id) const
void CountryInfoGetter::GetRegionInfo(string const & id, CountryInfo & info) const
{
string name;
map<string, CountryInfo>::const_iterator i = m_id2info.find(id);
ASSERT ( i != m_id2info.end(), () );
map<string, string>::const_iterator i = m_id2name.find(id);
if (i != m_id2name.end())
name = i->second;
else
name = id;
info = i->second;
if (info.m_name.empty())
info.m_name = id;
/// @todo Correct replace '_' with ", " in name.
if (id.find_first_of('_') != string::npos)
{
// I don't know how to do it best for UTF8, but this variant will work
// correctly for now (utf8-names of compound countries are equal to ascii-names).
size_t const i = info.m_name.find_first_of('_');
ASSERT ( i != string::npos, () );
size_t const i = name.find_first_of('_');
ASSERT_NOT_EQUAL ( i, string::npos, () );
name = name.substr(0, i) + ", " + name.substr(i+1);
// replace '_' with ", "
info.m_name[i] = ',';
info.m_name.insert(i+1, " ");
}
return name;
}
}

View file

@ -1,5 +1,6 @@
#pragma once
#include "country_polygon.hpp"
#include "country_decl.hpp"
#include "../geometry/region2d.hpp"
@ -15,7 +16,7 @@ namespace storage
FilesContainerR m_reader;
vector<CountryDef> m_countries;
map<string, string> m_id2name;
map<string, CountryInfo> m_id2info;
mutable my::Cache<uint32_t, vector<m2::RegionD> > m_cache;
@ -41,7 +42,8 @@ namespace storage
CountryInfoGetter(ModelReaderPtr polyR, ModelReaderPtr countryR);
string GetRegionFile(m2::PointD const & pt) const;
string GetRegionName(m2::PointD const & pt) const;
string GetRegionName(string const & id) const;
void GetRegionInfo(m2::PointD const & pt, CountryInfo & info) const;
void GetRegionInfo(string const & id, CountryInfo & info) const;
};
}

View file

@ -1,28 +1,15 @@
#pragma once
#include "../defines.hpp"
#include "country_decl.hpp"
#include "../indexer/point_to_int64.hpp"
#include "../indexer/coding_params.hpp"
#include "../geometry/rect2d.hpp"
#include "../coding/read_write_utils.hpp"
namespace storage
{
struct CountryDef
{
string m_name;
m2::RectD m_rect;
CountryDef() {}
CountryDef(string const & name, m2::RectD const & r)
: m_name(name), m_rect(r)
{
}
};
template <class TSource> void Read(TSource & src, CountryDef & p)
{
rw::Read(src, p.m_name);

View file

@ -18,6 +18,7 @@ HEADERS += \
storage.hpp \
country_polygon.hpp \
country_info.hpp \
country_decl.hpp \
SOURCES += \
country.cpp \

View file

@ -8,6 +8,8 @@
#include "../../platform/platform.hpp"
using namespace storage;
UNIT_TEST(CountryInfo_GetByPoint_Smoke)
{
Platform & pl = GetPlatform();
@ -16,9 +18,23 @@ UNIT_TEST(CountryInfo_GetByPoint_Smoke)
pl.GetReader(COUNTRIES_FILE));
// Minsk
TEST_EQUAL(getter.GetRegionName(
m2::PointD(MercatorBounds::LonToX(27.5618818),
MercatorBounds::LatToY(53.9022651))), "Belarus", ());
CountryInfo info;
getter.GetRegionInfo(m2::PointD(MercatorBounds::LonToX(27.5618818),
MercatorBounds::LatToY(53.9022651)),
info);
TEST_EQUAL(info.m_name, "Belarus", ());
TEST_EQUAL(info.m_flag, "by", ());
}
namespace
{
bool IsEmptyName(map<string, CountryInfo> const & id2info, string const & id)
{
map<string, CountryInfo>::const_iterator i = id2info.find(id);
TEST(i != id2info.end(), ());
return i->second.m_name.empty();
}
}
UNIT_TEST(CountryInfo_ValidName_Smoke)
@ -26,12 +42,12 @@ UNIT_TEST(CountryInfo_ValidName_Smoke)
string buffer;
ReaderPtr<Reader>(GetPlatform().GetReader(COUNTRIES_FILE)).ReadAsString(buffer);
map<string, string> id2name;
storage::LoadCountryFile2Name(buffer, id2name);
map<string, CountryInfo> id2info;
storage::LoadCountryFile2CountryInfo(buffer, id2info);
TEST(id2name.count("Germany_Baden-Wurttemberg") == 1, ());
TEST(id2name.count("France_Paris & Ile-de-France") == 1, ());
TEST(!IsEmptyName(id2info, "Germany_Baden-Wurttemberg"), ());
TEST(!IsEmptyName(id2info, "France_Paris & Ile-de-France"), ());
TEST(id2name.count("Russia_Far Eastern") == 0, ());
TEST(id2name.count("UK_Northern Ireland") == 0, ());
TEST(IsEmptyName(id2info, "Russia_Far Eastern"), ());
TEST(IsEmptyName(id2info, "UK_Northern Ireland"), ());
}