diff --git a/base/string_utils.cpp b/base/string_utils.cpp index 4456eb25c3..d91dc5bb0d 100644 --- a/base/string_utils.cpp +++ b/base/string_utils.cpp @@ -42,30 +42,31 @@ UniChar LastUniChar(string const & s) return *iter; } -bool to_int(char const * s, int & i, int base /*= 10*/) +namespace +{ +template +bool IntegerCheck(T x, char const *stop, ET & out) { - char * stop; - long const x = strtol(s, &stop, base); if (*stop == 0) { - i = static_cast(x); - ASSERT_EQUAL(static_cast(i), x, ()); + out = static_cast(x); + ASSERT_EQUAL(static_cast(out), x, ()); return true; } return false; } +} // namespace + +bool to_int(char const * s, int & i, int base /*= 10*/) +{ + char * stop; + return IntegerCheck(strtol(s, &stop, base), stop, i); +} bool to_uint(char const * s, unsigned int & i, int base /*= 10*/) { char * stop; - long const x = strtoul(s, &stop, base); - if (*stop == 0) - { - i = static_cast(x); - ASSERT_EQUAL(static_cast(i), x, ()); - return true; - } - return false; + return IntegerCheck(strtoul(s, &stop, base), stop, i); } diff --git a/generator/booking_dataset.cpp b/generator/booking_dataset.cpp index 56ba60a0bf..4f0df671de 100644 --- a/generator/booking_dataset.cpp +++ b/generator/booking_dataset.cpp @@ -13,6 +13,21 @@ namespace generator { + +namespace +{ +bool CheckForValues(string const & value) +{ + for (char const * val : + {"hotel", "apartment", "camp_site", "chalet", "guest_house", "hostel", "motel", "resort"}) + { + if (value == val) + return true; + } + return false; +} +} // namespace + BookingDataset::Hotel::Hotel(string const & src) { vector rec(FieldsCount()); @@ -42,22 +57,10 @@ ostream & operator<<(ostream & s, BookingDataset::Hotel const & h) return s << "Name: " << h.name << "\t Address: " << h.address << "\t lat: " << h.lat << " lon: " << h.lon; } -void BookingDataset::LoadHotels(string const & path) -{ - m_hotels.clear(); - - if (path.empty()) - return; - - ifstream src(path); - for (string line; getline(src, line);) - m_hotels.emplace_back(line); -} - BookingDataset::BookingDataset(string const & dataPath) { LoadHotels(dataPath); - + size_t counter = 0; for (auto const & hotel : m_hotels) { @@ -67,15 +70,166 @@ BookingDataset::BookingDataset(string const & dataPath) } } -bool CheckForValues(string const & value) +bool BookingDataset::BookingFilter(OsmElement const & e) const +{ + return Filter(e, [&](OsmElement const & e){ return MatchWithBooking(e); }); +} + +bool BookingDataset::TourismFilter(OsmElement const & e) const +{ + return Filter(e, [&](OsmElement const & e){ return true; }); +} + +BookingDataset::Hotel const & BookingDataset::GetHotel(size_t index) const +{ + ASSERT_GREATER(m_hotels.size(), index, ()); + return m_hotels[index]; +} + +vector BookingDataset::GetNearestHotels(double lat, double lon, size_t limit, + double maxDistance /* = 0.0 */) const +{ + namespace bgi = boost::geometry::index; + + vector indexes; + for_each(bgi::qbegin(m_rtree, bgi::nearest(TPoint(lat, lon), limit)), bgi::qend(m_rtree), + [&](TValue const & v) + { + auto const & hotel = m_hotels[v.second]; + double const dist = ms::DistanceOnEarth(lat, lon, hotel.lat, hotel.lon); + if (maxDistance != 0.0 && dist > maxDistance /* max distance in meters */) + return; + + indexes.emplace_back(v.second); + }); + return indexes; +} + +bool BookingDataset::MatchByName(string const & osmName, vector const & bookingIndexes) const { - for (char const * val : - {"hotel", "apartment", "camp_site", "chalet", "guest_house", "hostel", "motel", "resort"}) - { - if (value == val) - return true; - } return false; + + // Match name. +// vector osmTokens; +// NormalizeAndTokenizeString(name, osmTokens, search::Delimiters()); +// +// cout << "\n------------- " << name << endl; +// +// bool matched = false; +// for (auto const & index : indexes) +// { +// vector bookingTokens; +// NormalizeAndTokenizeString(m_hotels[index].name, bookingTokens, search::Delimiters()); +// +// map>> weightPair; +// +// for (size_t j = 0; j < osmTokens.size(); ++j) +// { +// for (size_t i = 0; i < bookingTokens.size(); ++i) +// { +// size_t distance = strings::EditDistance(osmTokens[j].begin(), osmTokens[j].end(), +// bookingTokens[i].begin(), bookingTokens[i].end()); +// if (distance < 3) +// weightPair[distance].emplace_back(i, j); +// } +// } +// +// if (!weightPair.empty()) +// { +// cout << m_hotels[e.second] << endl; +// matched = true; +// } +// } +} + +void BookingDataset::BuildFeatures(function const & fn) const +{ + for (auto const & hotel : m_hotels) + { + OsmElement e; + e.type = OsmElement::EntityType::Node; + e.id = 1; + + e.lat = hotel.lat; + e.lon = hotel.lon; + + e.AddTag("name", hotel.name); + e.AddTag("ref:sponsored", strings::to_string(hotel.id)); + e.AddTag("website", hotel.descUrl); + e.AddTag("rating:sponsored", strings::to_string(hotel.ratingUser)); + e.AddTag("stars", strings::to_string(hotel.stars)); + e.AddTag("price_rate", strings::to_string(hotel.priceCategory)); + e.AddTag("addr:full", hotel.address); + + switch (hotel.type) + { + case 19: + case 205: e.AddTag("tourism", "motel"); break; + + case 21: + case 206: + case 212: e.AddTag("tourism", "resort"); break; + + case 3: + case 23: + case 24: + case 25: + case 202: + case 207: + case 208: + case 209: + case 210: + case 216: + case 220: + case 223: e.AddTag("tourism", "guest_house"); break; + + case 14: + case 204: + case 213: + case 218: + case 219: + case 226: + case 222: e.AddTag("tourism", "hotel"); break; + + case 211: + case 224: + case 228: e.AddTag("tourism", "chalet"); break; + + case 13: + case 225: + case 203: e.AddTag("tourism", "hostel"); break; + + case 215: + case 221: + case 227: + case 2: + case 201: e.AddTag("tourism", "apartment"); break; + + case 214: e.AddTag("tourism", "camp_site"); break; + + default: e.AddTag("tourism", "hotel"); break; + } + + fn(&e); + } +} + +void BookingDataset::LoadHotels(string const & path) +{ + m_hotels.clear(); + + if (path.empty()) + return; + + ifstream src(path); + if (!src.is_open()) + { + LOG(LERROR, ("Error while opening", path, ":", strerror(errno))); + return; + } + + for (string line; getline(src, line);) + m_hotels.emplace_back(line); } bool BookingDataset::MatchWithBooking(OsmElement const & e) const @@ -89,84 +243,19 @@ bool BookingDataset::MatchWithBooking(OsmElement const & e) const break; } } - + if (name.empty()) return false; - + // Find 3 nearest values to a point. auto const indexes = GetNearestHotels(e.lat, e.lon, 3, 150 /* max distance in meters */); if (indexes.empty()) return false; - - // Match name. - vector osmTokens; - NormalizeAndTokenizeString(name, osmTokens, search::Delimiters()); - - // cout << "\n------------- " << name << endl; - - bool matched = false; - for (auto const & index : indexes) - { - vector bookingTokens; - NormalizeAndTokenizeString(m_hotels[index].name, bookingTokens, search::Delimiters()); - - map>> weightPair; - - for (size_t j = 0; j < osmTokens.size(); ++j) - { - for (size_t i = 0; i < bookingTokens.size(); ++i) - { - size_t distance = strings::EditDistance(osmTokens[j].begin(), osmTokens[j].end(), - bookingTokens[i].begin(), bookingTokens[i].end()); - if (distance < 3) - weightPair[distance].emplace_back(i, j); - } - } - - if (!weightPair.empty()) - { - // cout << m_hotels[e.second] << endl; - matched = true; - } - } + + bool matched = MatchByName(name, indexes); return matched; } -BookingDataset::Hotel const & BookingDataset::GetHotel(size_t index) const -{ - ASSERT_GREATER(m_hotels.size(), index, ()); - return m_hotels[index]; -} - -vector BookingDataset::GetNearestHotels(double lat, double lon, size_t limit, - double maxDistance /* = 0.0 */) const -{ - namespace bgi = boost::geometry::index; - - vector indexes; - for_each(bgi::qbegin(m_rtree, bgi::nearest(TPoint(lat, lon), limit)), bgi::qend(m_rtree), - [&](TValue const & v) - { - auto const & hotel = m_hotels[v.second]; - double const dist = ms::DistanceOnEarth(lat, lon, hotel.lat, hotel.lon); - if (maxDistance != 0.0 && dist > maxDistance /* max distance in meters */) - return; - - indexes.emplace_back(v.second); - }); - return indexes; -} - -bool BookingDataset::BookingFilter(OsmElement const & e) const -{ - return Filter(e, [&](OsmElement const & e){ return MatchWithBooking(e); }); -} - -bool BookingDataset::TourismFilter(OsmElement const & e) const -{ - return Filter(e, [&](OsmElement const & e){ return true; }); -} - bool BookingDataset::Filter(OsmElement const & e, function const & fn) const { if (e.type != OsmElement::EntityType::Node) @@ -190,76 +279,4 @@ bool BookingDataset::Filter(OsmElement const & e, function const & fn) const -{ - for (auto const & hotel : m_hotels) - { - OsmElement e; - e.type = OsmElement::EntityType::Node; - e.id = 1; - - e.lon = hotel.lon; - e.lat = hotel.lat; - - e.AddTag("name", hotel.name); - e.AddTag("ref:sponsored", strings::to_string(hotel.id)); - e.AddTag("website", hotel.descUrl); - e.AddTag("rating:sponsored", strings::to_string(hotel.ratingUser)); - e.AddTag("stars", strings::to_string(hotel.stars)); - e.AddTag("price_rate", strings::to_string(hotel.priceCategory)); - e.AddTag("addr:full", hotel.address); - - switch (hotel.type) - { - case 19: - case 205: e.AddTag("tourism", "motel"); break; - - case 21: - case 206: - case 212: e.AddTag("tourism", "resort"); break; - - case 3: - case 23: - case 24: - case 25: - case 202: - case 207: - case 208: - case 209: - case 210: - case 216: - case 220: - case 223: e.AddTag("tourism", "guest_house"); break; - - case 14: - case 204: - case 213: - case 218: - case 219: - case 226: - case 222: e.AddTag("tourism", "hotel"); break; - - case 211: - case 224: - case 228: e.AddTag("tourism", "chalet"); break; - - case 13: - case 225: - case 203: e.AddTag("tourism", "hostel"); break; - - case 215: - case 221: - case 227: - case 2: - case 201: e.AddTag("tourism", "apartment"); break; - - case 214: e.AddTag("tourism", "camp_site"); break; - - default: e.AddTag("tourism", "hotel"); break; - } - - fn(&e); - } -} - } // namespace generator diff --git a/generator/booking_dataset.hpp b/generator/booking_dataset.hpp index 79f5754265..d0810e0590 100644 --- a/generator/booking_dataset.hpp +++ b/generator/booking_dataset.hpp @@ -55,11 +55,12 @@ public: bool BookingFilter(OsmElement const & e) const; bool TourismFilter(OsmElement const & e) const; - void BuildFeatures(function const & fn) const; Hotel const & GetHotel(size_t index) const; vector GetNearestHotels(double lat, double lon, size_t limit, double maxDistance = 0.0) const; - + bool MatchByName(string const & osmName, vector const & bookingIndexes) const; + + void BuildFeatures(function const & fn) const; protected: vector m_hotels; @@ -71,8 +72,8 @@ protected: boost::geometry::index::rtree> m_rtree; void LoadHotels(string const & path); - bool Filter(OsmElement const & e, function const & fn) const; bool MatchWithBooking(OsmElement const & e) const; + bool Filter(OsmElement const & e, function const & fn) const; }; ostream & operator<<(ostream & s, BookingDataset::Hotel const & h);