From abfcfec733bfe1ef7f53d8e2a6ab253cd0c4d817 Mon Sep 17 00:00:00 2001 From: Sergey Magidovich Date: Wed, 21 Sep 2016 13:16:00 +0300 Subject: [PATCH] Add restaurants_info utility. --- coding/multilang_utf8_string.hpp | 2 +- .../restaurants_info/restaurants_info.cpp | 156 ++++++++++++++++++ .../restaurants_info/restaurants_info.pro | 24 +++ indexer/ftypes_matcher.cpp | 20 +++ indexer/ftypes_matcher.hpp | 7 + omim.pro | 5 + 6 files changed, 213 insertions(+), 1 deletion(-) create mode 100644 generator/restaurants_info/restaurants_info.cpp create mode 100644 generator/restaurants_info/restaurants_info.pro diff --git a/coding/multilang_utf8_string.hpp b/coding/multilang_utf8_string.hpp index 67323ca3ca..fc547cd327 100644 --- a/coding/multilang_utf8_string.hpp +++ b/coding/multilang_utf8_string.hpp @@ -105,7 +105,7 @@ public: else return false; } - + bool HasString(int8_t lang) const; int8_t FindString(string const & utf8s) const; diff --git a/generator/restaurants_info/restaurants_info.cpp b/generator/restaurants_info/restaurants_info.cpp new file mode 100644 index 0000000000..ed1f862576 --- /dev/null +++ b/generator/restaurants_info/restaurants_info.cpp @@ -0,0 +1,156 @@ +#include "generator/feature_builder.hpp" +#include "generator/osm_source.hpp" + +#include "indexer/classificator.hpp" +#include "indexer/classificator_loader.hpp" +#include "indexer/ftypes_matcher.hpp" + +#include "geometry/distance_on_sphere.hpp" +#include "geometry/mercator.hpp" + +#include "base/logging.hpp" +#include "base/string_utils.hpp" + +#include "std/cstdint.hpp" +#include "std/fstream.hpp" +#include "std/sstream.hpp" +#include "std/unique_ptr.hpp" +#include "std/vector.hpp" + +#include "gflags/gflags.h" + +DEFINE_string(osm, "", "Input .o5m file"); +DEFINE_string(out, "", "Output file path"); + +namespace +{ +class Emitter : public EmitterBase +{ +public: + Emitter(vector & features) + : m_features(features) + { + LOG_SHORT(LINFO, ("OSM data:", FLAGS_osm)); + } + + // EmitterBase overrides: + void operator()(FeatureBuilder1 & fb) override + { + if (!ftypes::IsFoodChecker::Instance()(fb.GetParams().m_Types) || fb.GetParams().name.IsEmpty()) + { + ++m_stats.m_unexpectedFeatures; + return; + } + + switch (fb.GetGeomType()) + { + case feature::GEOM_POINT: ++m_stats.m_restaurantsPoi; break; + case feature::GEOM_AREA: ++m_stats.m_restaurantsBuilding; break; + default: ++m_stats.m_unexpectedFeatures; + } + m_features.emplace_back(fb); + } + + void GetNames(vector & names) const override + { + // We do not need to create any data file. See generator_tool.cpp and osm_source.cpp. + names.clear(); + } + + bool Finish() override + { + LOG_SHORT(LINFO, ("Number of restaurants: POI:", m_stats.m_restaurantsPoi, + "BUILDING:", m_stats.m_restaurantsBuilding, + "TOTAL:", m_features.size(), + "INVALID:", m_stats.m_unexpectedFeatures)); + return true; + } + +private: + vector & m_features; + + struct Stats + { + // Number of features of any "food type". + uint32_t m_restaurantsPoi = 0; + uint32_t m_restaurantsBuilding = 0; + uint32_t m_unexpectedFeatures = 0; + }; + + Stats m_stats; +}; + +feature::GenerateInfo GetGenerateInfo() +{ + feature::GenerateInfo info; + info.m_osmFileName = FLAGS_osm; + info.SetNodeStorageType("map"); + info.SetOsmFileType("o5m"); + + info.m_intermediateDir = my::GetDirectory(FLAGS_out); + + // Set other info params here. + + return info; +} + +void DumpRestaurants(vector const & features, ostream & out) +{ + for (auto const & f : features) + { + auto const multilangName = f.GetParams().name; + + string defaultName; + vector translations; + multilangName.ForEach([&translations, &defaultName](uint8_t const langCode, string const & name) + { + if (langCode == StringUtf8Multilang::kDefaultCode) + { + defaultName = name; + return true; + } + translations.push_back(name); + return true; + }); + auto const center = MercatorBounds::ToLatLon(f.GetKeyPoint()); + + out << defaultName << '\t' << strings::JoinStrings(translations, '|') << '\t' + << center.lat << ' ' << center.lon << '\t' << DebugPrint(f.GetGeomType()) << "\n"; + } +} +} // namespace + +int main(int argc, char * argv[]) +{ + google::SetUsageMessage("Dump restaurants in tsv format."); + + if (argc == 1) + { + google::ShowUsageWithFlags(argv[0]); + exit(0); + } + + google::ParseCommandLineFlags(&argc, &argv, true); + + CHECK(!FLAGS_osm.empty(), ("Please specify osm path.")); + CHECK(!FLAGS_out.empty(), ("Please specify output file path.")); + + classificator::Load(); + + auto info = GetGenerateInfo(); + GenerateIntermediateData(info); + + vector features; + GenerateFeatures(info, [&features](feature::GenerateInfo const & /* info */) + { + return make_unique(features); + }); + + { + ofstream ost(FLAGS_out); + CHECK(ost.is_open(), ("Can't open file", FLAGS_out, strerror(errno))); + DumpRestaurants(features, ost); + } + + return 0; +} diff --git a/generator/restaurants_info/restaurants_info.pro b/generator/restaurants_info/restaurants_info.pro new file mode 100644 index 0000000000..8573860df1 --- /dev/null +++ b/generator/restaurants_info/restaurants_info.pro @@ -0,0 +1,24 @@ +# Base functions tests. + +TARGET = restaurants_info +CONFIG += console warn_on +CONFIG -= app_bundle +TEMPLATE = app + +ROOT_DIR = ../.. +DEPENDENCIES = \ + generator search routing indexer geometry \ + editor platform coding base tomcrypt jansson \ + pugixml stats_client opening_hours gflags \ + oauthcpp expat protobuf \ + +include($$ROOT_DIR/common.pri) + +INCLUDEPATH *= $$ROOT_DIR/3party/gflags/src + +QT *= core + +SOURCES += \ + restaurants_info.cpp \ + +HEADERS += diff --git a/indexer/ftypes_matcher.cpp b/indexer/ftypes_matcher.cpp index 67a1291059..dfe0a32004 100644 --- a/indexer/ftypes_matcher.cpp +++ b/indexer/ftypes_matcher.cpp @@ -456,6 +456,26 @@ IsWifiChecker const & IsWifiChecker::Instance() return instance; } +IsFoodChecker:: IsFoodChecker() +{ + Classificator const & c = classif(); + char const * const paths[][2] = { + {"amenity", "cafe"}, + {"amenity", "bar"}, + {"amenity", "pub"}, + {"amenity", "fast_food"}, + {"amenity", "restaurant"} + }; + for (auto const & path : paths) + m_types.push_back(c.GetTypeByPath({path[0], path[1]})); +} + +IsFoodChecker const & IsFoodChecker::Instance() +{ + static const IsFoodChecker instance; + return instance; +} + uint32_t GetPopulation(FeatureType const & ft) { uint32_t population = ft.GetPopulation(); diff --git a/indexer/ftypes_matcher.hpp b/indexer/ftypes_matcher.hpp index 5effd53211..2e8fd6bc3e 100644 --- a/indexer/ftypes_matcher.hpp +++ b/indexer/ftypes_matcher.hpp @@ -183,6 +183,13 @@ public: static IsWifiChecker const & Instance(); }; +class IsFoodChecker : public BaseChecker +{ + IsFoodChecker(); +public: + static IsFoodChecker const & Instance(); +}; + /// Type of locality (do not change values and order - they have detalization order) /// COUNTRY < STATE < CITY < ... enum Type { NONE = -1, COUNTRY = 0, STATE, CITY, TOWN, VILLAGE, LOCALITY_COUNT }; diff --git a/omim.pro b/omim.pro index 932aec851d..7afb01833c 100644 --- a/omim.pro +++ b/omim.pro @@ -46,6 +46,11 @@ SUBDIRS = 3party base coding geometry editor indexer routing search booking_quality_check.depends = $$SUBDIRS SUBDIRS *= booking_quality_check + # restaraunts_info + restaurants_info.subdir = generator/restaurants_info + restaurants_info.depends = $$SUBDIRS + SUBDIRS *= restaurants_info + routing_integration_tests.subdir = routing/routing_integration_tests routing_integration_tests.depends = $$SUBDIRS routing_consistency_tests.subdir = routing/routing_consistency_tests