diff options
author | Sergey Magidovich <mgsergio@mapswithme.com> | 2016-07-30 16:35:14 +0300 |
---|---|---|
committer | Sergey Magidovich <mgsergio@mapswithme.com> | 2016-08-02 17:04:05 +0300 |
commit | 177a515c8581e7b9e51206449efce5d8d6853cff (patch) | |
tree | 42b7d849e76a41ea6576593aeb62c30039e63ea3 /generator | |
parent | 9d821509fe11748aa6f2045dd78f2d7feb27d415 (diff) |
Use FeatureBuilder insted of OsmelElement to handle geometry.
Handle booking in Emitter.
Diffstat (limited to 'generator')
-rw-r--r-- | generator/booking_dataset.cpp | 181 | ||||
-rw-r--r-- | generator/booking_dataset.hpp | 18 | ||||
-rw-r--r-- | generator/booking_quality_check/booking_quality_check.cpp | 212 | ||||
-rw-r--r-- | generator/booking_scoring.cpp | 11 | ||||
-rw-r--r-- | generator/booking_scoring.hpp | 4 | ||||
-rw-r--r-- | generator/osm_source.cpp | 61 |
6 files changed, 278 insertions, 209 deletions
diff --git a/generator/booking_dataset.cpp b/generator/booking_dataset.cpp index 60745a6364..d9e0945ed1 100644 --- a/generator/booking_dataset.cpp +++ b/generator/booking_dataset.cpp @@ -1,10 +1,12 @@ #include "generator/booking_dataset.hpp" #include "generator/booking_scoring.hpp" +#include "generator/feature_builder.hpp" #include "platform/local_country_file_utils.hpp" #include "platform/platform.hpp" +#include "indexer/classificator.hpp" #include "indexer/ftypes_matcher.hpp" #include "geometry/distance_on_sphere.hpp" @@ -14,18 +16,13 @@ #include "std/fstream.hpp" #include "std/iostream.hpp" +#include "std/limits.hpp" #include "std/sstream.hpp" namespace generator { namespace { -bool CheckForValues(string const & value) -{ - auto const & tags = ftypes::IsHotelChecker::GetHotelTags(); - return find(tags.begin(), tags.end(), value) != tags.end(); -} - string EscapeTabs(string const & str) { stringstream ss; @@ -124,20 +121,17 @@ BookingDataset::BookingDataset(istream & dataSource, string const & addressRefer LoadHotels(dataSource, addressReferencePath); } -bool BookingDataset::BookingFilter(OsmElement const & e) const +size_t BookingDataset::GetMatchingHotelIndex(FeatureBuilder1 const & fb) const { - return Filter(e, [&](OsmElement const & e) - { - return MatchWithBooking(e); - }); + if (CanBeBooking(fb)) + return MatchWithBooking(fb); + return numeric_limits<size_t>::max(); } -bool BookingDataset::TourismFilter(OsmElement const & e) const +// TODO(mgsergio): rename to ... or delete. +bool BookingDataset::TourismFilter(FeatureBuilder1 const & fb) const { - return Filter(e, [&](OsmElement const & e) - { - return true; - }); + return CanBeBooking(fb); } BookingDataset::Hotel const & BookingDataset::GetHotel(size_t index) const @@ -161,64 +155,71 @@ vector<size_t> BookingDataset::GetNearestHotels(double lat, double lon, size_t l 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]; + auto const & hotel = GetHotel(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; } -void BookingDataset::BuildFeatures(function<void(OsmElement *)> const & fn) const +void BookingDataset::BuildFeature(FeatureBuilder1 const & /*fb*/, size_t const hotelIndex, + function<void(FeatureBuilder1 &)> 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("sponsored", "booking"); - 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); - - if (!hotel.translations.empty()) - { - vector<string> parts; - strings::ParseCSVRow(hotel.translations, '|', parts); - CHECK(parts.size() % 3 == 0, ()); - for (auto i = 0; i < parts.size(); i += 3) - { - e.AddTag("name:" + parts[i], parts[i + 1]); - e.AddTag("addr:full:" + parts[i], parts[i + 2]); - } - } + auto const & hotel = m_hotels[hotelIndex]; - if (!hotel.street.empty()) - e.AddTag("addr:street", hotel.street); + FeatureBuilder1 bookingFb; + FeatureParams params; + // TODO(mgsergio): handle areas. + bookingFb.SetCenter(MercatorBounds::FromLatLon(hotel.lat, hotel.lon)); - if (!hotel.houseNumber.empty()) - e.AddTag("addr:housenumber", hotel.houseNumber); + auto & metadata = params.GetMetadata(); + metadata.Set(feature::Metadata::FMD_SPONSORED_ID, strings::to_string(hotel.id)); + metadata.Set(feature::Metadata::FMD_WEBSITE, hotel.descUrl); + metadata.Set(feature::Metadata::FMD_RATING, strings::to_string(hotel.ratingUser)); + metadata.Set(feature::Metadata::FMD_STARS, strings::to_string(hotel.stars)); + metadata.Set(feature::Metadata::FMD_PRICE_RATE, strings::to_string(hotel.priceCategory)); - // Matching booking.com hotel types to OpenStreetMap values. - // Booking types are listed in the closed API docs. - switch (hotel.type) + // params.AddAddress(hotel.address); + // TODO(mgsergio): addr:full ??? + + if (!hotel.street.empty()) + bookingFb.AddStreet(hotel.street); + + if (!hotel.houseNumber.empty()) + bookingFb.AddHouseNumber(hotel.houseNumber); + + params.AddName(StringUtf8Multilang::GetLangByCode(StringUtf8Multilang::kDefaultCode), + hotel.name); + if (!hotel.translations.empty()) + { + // TODO(mgsergio): Move parsing to the hotel costruction stage. + vector<string> parts; + strings::ParseCSVRow(hotel.translations, '|', parts); + CHECK(parts.size() % 3 == 0, ()); + for (auto i = 0; i < parts.size(); i += 3) { + auto const langCode = StringUtf8Multilang::GetLangIndex(parts[i]); + params.AddName(StringUtf8Multilang::GetLangByCode(langCode), parts[i + 1]); + // TODO(mgsergio): e.AddTag("addr:full:" + parts[i], parts[i + 2]); + } + } + + auto const & clf = classif(); + params.AddType(clf.GetTypeByPath({"sponsored", "booking"})); + // Matching booking.com hotel types to OpenStreetMap values. + // Booking types are listed in the closed API docs. + switch (hotel.type) + { case 19: - case 205: e.AddTag("tourism", "motel"); break; + case 205: params.AddType(clf.GetTypeByPath({"tourism", "motel"})); break; case 21: case 206: - case 212: e.AddTag("tourism", "resort"); break; + case 212: params.AddType(clf.GetTypeByPath({"tourism", "resort"})); break; case 3: case 23: @@ -231,7 +232,7 @@ void BookingDataset::BuildFeatures(function<void(OsmElement *)> const & fn) cons case 210: case 216: case 220: - case 223: e.AddTag("tourism", "guest_house"); break; + case 223: params.AddType(clf.GetTypeByPath({"tourism", "guest_house"})); break; case 14: case 204: @@ -239,29 +240,30 @@ void BookingDataset::BuildFeatures(function<void(OsmElement *)> const & fn) cons case 218: case 219: case 226: - case 222: e.AddTag("tourism", "hotel"); break; + case 222: params.AddType(clf.GetTypeByPath({"tourism", "hotel"})); break; case 211: case 224: - case 228: e.AddTag("tourism", "chalet"); break; + case 228: params.AddType(clf.GetTypeByPath({"tourism", "chalet"})); break; case 13: case 225: - case 203: e.AddTag("tourism", "hostel"); break; + case 203: params.AddType(clf.GetTypeByPath({"tourism", "hostel"})); break; case 215: case 221: case 227: case 2: - case 201: e.AddTag("tourism", "apartment"); break; + case 201: params.AddType(clf.GetTypeByPath({"tourism", "apartment"})); break; - case 214: e.AddTag("tourism", "camp_site"); break; + case 214: params.AddType(clf.GetTypeByPath({"tourism", "camp_site"})); break; - default: e.AddTag("tourism", "hotel"); break; - } - - fn(&e); + default: params.AddType(clf.GetTypeByPath({"tourism", "hotel"})); break; } + + bookingFb.SetParams(params); + + fn(bookingFb); } void BookingDataset::LoadHotels(istream & src, string const & addressReferencePath) @@ -306,58 +308,37 @@ void BookingDataset::LoadHotels(istream & src, string const & addressReferencePa } } -bool BookingDataset::MatchWithBooking(OsmElement const & e) const +size_t BookingDataset::MatchWithBooking(FeatureBuilder1 const & fb) const { - string name; - for (auto const & tag : e.Tags()) - { - if (tag.key == "name") - { - name = tag.value; - break; - } - } + auto const name = fb.GetName(StringUtf8Multilang::kDefaultCode); if (name.empty()) return false; + auto const center = MercatorBounds::ToLatLon(fb.GetKeyPoint()); // Find |kMaxSelectedElements| nearest values to a point. auto const bookingIndexes = - GetNearestHotels(e.lat, e.lon, kMaxSelectedElements, kDistanceLimitInMeters); - - bool matched = false; + GetNearestHotels(center.lat, center.lon, kMaxSelectedElements, kDistanceLimitInMeters); for (size_t const j : bookingIndexes) { - if (booking_scoring::Match(GetHotel(j), e).IsMatched()) - break; + if (booking_scoring::Match(GetHotel(j), fb).IsMatched()) + return j; } - return matched; + return numeric_limits<size_t>::max(); } -bool BookingDataset::Filter(OsmElement const & e, - function<bool(OsmElement const &)> const & fn) const +bool BookingDataset::CanBeBooking(FeatureBuilder1 const & fb) const { - if (e.type != OsmElement::EntityType::Node) + // TODO(mgsergio): Remove me after refactoring is done and tested. + // Or remove the entire filter func. + if (fb.GetGeomType() != feature::GEOM_POINT) return false; - if (e.Tags().empty()) + if (fb.GetName(StringUtf8Multilang::kDefaultCode).empty()) return false; - bool matched = false; - for (auto const & tag : e.Tags()) - { - if (tag.key == "tourism" && CheckForValues(tag.value)) - { - matched = fn(e); - break; - } - } - - // TODO: Need to write file with dropped osm features. - - return matched; + return ftypes::IsHotelChecker::Instance()(fb.GetTypes()); } - } // namespace generator diff --git a/generator/booking_dataset.hpp b/generator/booking_dataset.hpp index c37859cca6..9de339d500 100644 --- a/generator/booking_dataset.hpp +++ b/generator/booking_dataset.hpp @@ -1,7 +1,5 @@ #pragma once -#include "generator/osm_element.hpp" - #include "indexer/index.hpp" #include "search/reverse_geocoder.hpp" @@ -14,6 +12,8 @@ #include "std/function.hpp" #include "std/string.hpp" +class FeatureBuilder1; + namespace generator { class BookingDataset @@ -77,8 +77,9 @@ public: explicit BookingDataset(string const & dataPath, string const & addressReferencePath = string()); explicit BookingDataset(istream & dataSource, string const & addressReferencePath = string()); - bool BookingFilter(OsmElement const & e) const; - bool TourismFilter(OsmElement const & e) const; + /// @returns an index of a matched hotel or numeric_limits<size_t>::max on failure. + size_t GetMatchingHotelIndex(FeatureBuilder1 const & e) const; + bool TourismFilter(FeatureBuilder1 const & e) const; inline size_t Size() const { return m_hotels.size(); } Hotel const & GetHotel(size_t index) const; @@ -87,7 +88,8 @@ public: double maxDistance = 0.0) const; bool MatchByName(string const & osmName, vector<size_t> const & bookingIndexes) const; - void BuildFeatures(function<void(OsmElement *)> const & fn) const; + void BuildFeature(FeatureBuilder1 const & fb, size_t hotelIndex, + function<void(FeatureBuilder1 &)> const & fn) const; protected: vector<Hotel> m_hotels; @@ -100,10 +102,10 @@ protected: boost::geometry::index::rtree<TValue, boost::geometry::index::quadratic<16>> m_rtree; void LoadHotels(istream & path, string const & addressReferencePath); - bool MatchWithBooking(OsmElement const & e) const; - bool Filter(OsmElement const & e, function<bool(OsmElement const &)> const & fn) const; + /// @returns an index of a matched hotel or numeric_limits<size_t>::max() on failure. + size_t MatchWithBooking(FeatureBuilder1 const & e) const; + bool CanBeBooking(FeatureBuilder1 const & e) const; }; ostream & operator<<(ostream & s, BookingDataset::Hotel const & h); - } // namespace generator diff --git a/generator/booking_quality_check/booking_quality_check.cpp b/generator/booking_quality_check/booking_quality_check.cpp index b4e817fc18..1df4239bdd 100644 --- a/generator/booking_quality_check/booking_quality_check.cpp +++ b/generator/booking_quality_check/booking_quality_check.cpp @@ -1,17 +1,21 @@ #include "generator/booking_dataset.hpp" #include "generator/booking_scoring.hpp" +#include "generator/feature_builder.hpp" #include "generator/osm_source.hpp" +#include "indexer/classificator_loader.hpp" + #include "geometry/distance_on_sphere.hpp" #include "std/fstream.hpp" #include "std/iostream.hpp" #include "std/numeric.hpp" #include "std/random.hpp" +#include "std/unique_ptr.hpp" #include "3party/gflags/src/gflags/gflags.h" -DEFINE_bool(generate_classif, false, "Generate classificator."); +// TODO(mgsergio):Unused: DEFINE_bool(generate_classif, false, "Generate classificator."); DEFINE_string(osm_file_name, "", "Input .o5m file"); DEFINE_string(booking_data, "", "Path to booking data in .tsv format"); @@ -21,93 +25,163 @@ DEFINE_uint64(seed, minstd_rand::default_seed, "Seed for random shuffle"); using namespace generator; -ostream & operator<<(ostream & s, OsmElement const & e) +namespace { - for (auto const & tag : e.Tags()) - { - auto t = tag; - replace(t.key.begin(), t.key.end(), '\n', ' '); - replace(t.value.begin(), t.value.end(), '\n', ' '); - s << t.key << "=" << t.value << "\t"; - } - return s; -} - -int main(int argc, char * argv[]) +string PrintBuilder(FeatureBuilder1 const & fb) { - google::SetUsageMessage( - "Takes OSM XML data from stdin and creates" - " data and index files in several passes."); - google::ParseCommandLineFlags(&argc, &argv, true); + ostringstream s; - LOG_SHORT(LINFO, ("Booking data:", FLAGS_booking_data)); + s << "Name: " << fb.GetName(StringUtf8Multilang::kDefaultCode) << '\t'; - BookingDataset bookingDataset(FLAGS_booking_data); + auto const params = fb.GetParams(); + auto const street = params.GetStreet(); + auto const house = params.house.Get(); - vector<OsmElement> elements; - LOG_SHORT(LINFO, ("OSM data:", FLAGS_osm_file_name)); + string address = street; + if (!house.empty()) { - SourceReader reader = - FLAGS_osm_file_name.empty() ? SourceReader() : SourceReader(FLAGS_osm_file_name); - ProcessOsmElementsFromO5M(reader, [&](OsmElement * e) - { - if (bookingDataset.TourismFilter(*e)) - elements.emplace_back(*e); - }); + if (!street.empty()) + address += ", "; + address += house; } - LOG_SHORT(LINFO, ("Num of tourism elements:", elements.size())); - vector<size_t> elementIndexes(elements.size()); - iota(elementIndexes.begin(), elementIndexes.end(), 0); + if (!address.empty()) + s << "Address: " << address << '\t'; - shuffle(elementIndexes.begin(), elementIndexes.end(), minstd_rand(FLAGS_seed)); - if (FLAGS_selection_size < elementIndexes.size()) - elementIndexes.resize(FLAGS_selection_size); + auto const center = MercatorBounds::ToLatLon(fb.GetKeyPoint()); + s << "lat: " << center.lat << " lon: " << center.lon << '\t'; - stringstream outStream; + return s.str(); +} - for (size_t i : elementIndexes) +struct Emitter : public EmitterBase +{ + Emitter(feature::GenerateInfo const & info) + : m_bookingDataset(info.m_bookingDatafileName) { - OsmElement const & e = elements[i]; - auto const bookingIndexes = bookingDataset.GetNearestHotels( - e.lat, e.lon, BookingDataset::kMaxSelectedElements, BookingDataset::kDistanceLimitInMeters); - for (size_t const j : bookingIndexes) - { - auto const & hotel = bookingDataset.GetHotel(j); - auto const score = booking_scoring::Match(hotel, e); - - double const distanceMeters = ms::DistanceOnEarth(e.lat, e.lon, hotel.lat, hotel.lon); - bool matched = score.IsMatched(); - - outStream << "# ------------------------------------------" << fixed << setprecision(6) - << endl; - outStream << (matched ? 'y' : 'n') << " \t" << i << "\t " << j - << "\tdistance: " << distanceMeters - << "\tdistance score: " << score.m_linearNormDistanceScore - << "\tname score: " << score.m_nameSimilarityScore - << "\tresult score: " << score.GetMatchingScore() - << endl; - outStream << "# " << e << endl; - outStream << "# " << hotel << endl; - outStream << "# URL: https://www.openstreetmap.org/?mlat=" << hotel.lat - << "&mlon=" << hotel.lon << "#map=18/" << hotel.lat << "/" << hotel.lon << endl; - } - if (!bookingIndexes.empty()) - outStream << endl << endl; + LOG_SHORT(LINFO, (m_bookingDataset.Size(), "hotels are loaded from Booking.")); + LOG_SHORT(LINFO, ("OSM data:", FLAGS_osm_file_name)); } - if (FLAGS_sample_data.empty()) + void operator()(FeatureBuilder1 & fb) override { - cout << outStream.str(); + if (m_bookingDataset.TourismFilter(fb)) + m_features.emplace_back(fb); } - else + + void GetNames(vector<string> & names) const override + { + names.clear(); + } + + bool Finish() override { - ofstream file(FLAGS_sample_data); - if (file.is_open()) - file << outStream.str(); + LOG_SHORT(LINFO, ("Num of tourism elements:", m_features.size())); + vector<size_t> elementIndexes(m_features.size()); + iota(elementIndexes.begin(), elementIndexes.end(), 0); + + shuffle(elementIndexes.begin(), elementIndexes.end(), minstd_rand(FLAGS_seed)); + if (FLAGS_selection_size < elementIndexes.size()) + elementIndexes.resize(FLAGS_selection_size); + + stringstream outStream; + + for (size_t i : elementIndexes) + { + auto const & fb = m_features[i]; + auto const center = MercatorBounds::ToLatLon(fb.GetKeyPoint()); + auto const bookingIndexes = m_bookingDataset.GetNearestHotels( + center.lat, center.lon, + BookingDataset::kMaxSelectedElements, + BookingDataset::kDistanceLimitInMeters); + + for (size_t const j : bookingIndexes) + { + auto const & hotel = m_bookingDataset.GetHotel(j); + auto const score = booking_scoring::Match(hotel, fb); + + double const distanceMeters = ms::DistanceOnEarth(center.lat, center.lon, + hotel.lat, hotel.lon); + auto const matched = score.IsMatched(); + + outStream << "# ------------------------------------------" << fixed << setprecision(6) + << endl; + outStream << (matched ? 'y' : 'n') << " \t" << i << "\t " << j + << "\tdistance: " << distanceMeters + << "\tdistance score: " << score.m_linearNormDistanceScore + << "\tname score: " << score.m_nameSimilarityScore + << "\tresult score: " << score.GetMatchingScore() + << endl; + outStream << "# " << PrintBuilder(fb) << endl; + outStream << "# " << hotel << endl; + outStream << "# URL: https://www.openstreetmap.org/?mlat=" << hotel.lat + << "&mlon=" << hotel.lon << "#map=18/" << hotel.lat << "/" << hotel.lon << endl; + } + if (!bookingIndexes.empty()) + outStream << endl << endl; + } + + if (FLAGS_sample_data.empty()) + { + cout << outStream.str(); + } else - LOG(LERROR, ("Can't output into", FLAGS_sample_data)); + { + ofstream file(FLAGS_sample_data); + if (file.is_open()) + { + file << outStream.str(); + } + else + { + LOG(LERROR, ("Can't output into", FLAGS_sample_data)); + return false; + } + } + + return true; } + BookingDataset m_bookingDataset; + vector<FeatureBuilder1> m_features; +}; + +unique_ptr<Emitter> GetEmitter(feature::GenerateInfo const & info) +{ + LOG_SHORT(LINFO, ("Booking data:", FLAGS_booking_data)); + return make_unique<Emitter>(info); +} + +feature::GenerateInfo GetGenerateInfo() +{ + feature::GenerateInfo info; + info.m_bookingDatafileName = FLAGS_booking_data; + info.m_osmFileName = FLAGS_osm_file_name; + info.SetNodeStorageType("map"); + info.SetOsmFileType("o5m"); + + auto const lastSlash = FLAGS_sample_data.rfind("/"); + if (lastSlash == string::npos) + info.m_intermediateDir = "."; + else + info.m_intermediateDir = FLAGS_sample_data.substr(0, lastSlash); + // ... + return info; +} +} // namespace + +int main(int argc, char * argv[]) +{ + google::SetUsageMessage( + "Takes OSM XML data from stdin and creates" + " data and index files in several passes."); + google::ParseCommandLineFlags(&argc, &argv, true); + + classificator::Load(); + + auto info = GetGenerateInfo(); + GenerateIntermediateData(info); + GenerateFeatures(info, GetEmitter); + return 0; } diff --git a/generator/booking_scoring.cpp b/generator/booking_scoring.cpp index 2ddd071f6f..3c5941b325 100644 --- a/generator/booking_scoring.cpp +++ b/generator/booking_scoring.cpp @@ -1,6 +1,7 @@ #include "generator/booking_scoring.hpp" #include "generator/booking_dataset.hpp" +#include "generator/feature_builder.hpp" #include "indexer/search_delimiters.hpp" #include "indexer/search_string_utils.hpp" @@ -20,7 +21,7 @@ namespace booking_scoring namespace { // Calculated with tools/python/booking_hotels_quality.py. -double constexpr kOptimalThreshold = 0.317324; +double constexpr kOptimalThreshold = 0.321098; template <typename T, typename U> struct decay_equiv : @@ -125,15 +126,17 @@ bool BookingMatchScore::IsMatched() const return GetMatchingScore() > kOptimalThreshold; } -BookingMatchScore Match(BookingDataset::Hotel const & h, OsmElement const & e) +BookingMatchScore Match(BookingDataset::Hotel const & h, FeatureBuilder1 const & fb) { BookingMatchScore score; - auto const distance = ms::DistanceOnEarth(e.lat, e.lon, h.lat, h.lon); + auto const fbCenter = MercatorBounds::ToLatLon(fb.GetKeyPoint()); + auto const distance = ms::DistanceOnEarth(fbCenter.lat, fbCenter.lon, h.lat, h.lon); score.m_linearNormDistanceScore = GetLinearNormDistanceScore(distance); // TODO(mgsergio): Check all translations and use the best one. - score.m_nameSimilarityScore = GetNameSimilarityScore(h.name, e.GetTag("name")); + score.m_nameSimilarityScore = + GetNameSimilarityScore(h.name, fb.GetName(StringUtf8Multilang::kDefaultCode)); return score; } diff --git a/generator/booking_scoring.hpp b/generator/booking_scoring.hpp index e5516a4470..225fe4822b 100644 --- a/generator/booking_scoring.hpp +++ b/generator/booking_scoring.hpp @@ -2,7 +2,7 @@ #include "generator/booking_dataset.hpp" -struct OsmElement; +class FeatureBuilder1; namespace generator { @@ -17,6 +17,6 @@ struct BookingMatchScore double m_nameSimilarityScore{}; }; -BookingMatchScore Match(BookingDataset::Hotel const & h, OsmElement const & e); +BookingMatchScore Match(BookingDataset::Hotel const & h, FeatureBuilder1 const & fb); } // namespace booking_scoring } // namespace generator diff --git a/generator/osm_source.cpp b/generator/osm_source.cpp index d9e43bec2f..cf337c8eec 100644 --- a/generator/osm_source.cpp +++ b/generator/osm_source.cpp @@ -23,6 +23,7 @@ #include "coding/parse_xml.hpp" #include "std/fstream.hpp" +#include "std/limits.hpp" #include "defines.hpp" @@ -269,6 +270,8 @@ class MainFeaturesEmitter : public EmitterBase string m_srcCoastsFile; bool m_failOnCoasts; + generator::BookingDataset m_bookingDataset; + // TODO(mgsergio): comment. m4::Tree<Place> m_places; @@ -288,6 +291,7 @@ class MainFeaturesEmitter : public EmitterBase public: MainFeaturesEmitter(feature::GenerateInfo const & info) : m_failOnCoasts(info.m_failOnCoasts) + , m_bookingDataset(info.m_bookingDatafileName, info.m_bookingReferenceDir) { Classificator const & c = classif(); @@ -329,6 +333,8 @@ public: static uint32_t const placeType = classif().GetTypeByPath({"place"}); uint32_t const type = fb.GetParams().FindType(placeType, 1); + auto hotelIndex = numeric_limits<size_t>::max(); + if (type != ftype::GetEmptyValue() && !fb.GetName().empty()) { m_places.ReplaceEqualInRect( @@ -336,6 +342,11 @@ public: [](Place const & p1, Place const & p2) { return p1.IsEqual(p2); }, [](Place const & p1, Place const & p2) { return p1.IsBetterThan(p2); }); } + else if ((hotelIndex = m_bookingDataset.GetMatchingHotelIndex(fb)) != + numeric_limits<size_t>::max()) + { + m_bookingDataset.BuildFeature(fb, hotelIndex, [this](FeatureBuilder1 & fb) { Emit(fb); }); + } else { Emit(fb); @@ -621,11 +632,8 @@ bool GenerateFeaturesImpl(feature::GenerateInfo & info, EmitterBase & emitter) TagReplacer tagReplacer(GetPlatform().ResourcesDir() + REPLACED_TAGS_FILE); OsmTagMixer osmTagMixer(GetPlatform().ResourcesDir() + MIXED_TAGS_FILE); - // If info.m_bookingDatafileName is empty then no data will be loaded. - generator::BookingDataset bookingDataset(info.m_bookingDatafileName, - info.m_bookingReferenceDir); - - stringstream skippedElements; + // TODO(mgsergio): Output skipped elemnts. + // stringstream skippedElements; // Here we can add new tags to element!!! auto const fn = [&](OsmElement * e) @@ -634,11 +642,11 @@ bool GenerateFeaturesImpl(feature::GenerateInfo & info, EmitterBase & emitter) tagAdmixer(e); osmTagMixer(e); - if (bookingDataset.BookingFilter(*e)) - { - skippedElements << e->id << endl; - return; - } + // if (bookingDataset.BookingFilter(*e)) + // { + // skippedElements << e->id << endl; + // return; + // } parser.EmitElement(e); }; @@ -656,22 +664,23 @@ bool GenerateFeaturesImpl(feature::GenerateInfo & info, EmitterBase & emitter) LOG(LINFO, ("Processing", info.m_osmFileName, "done.")); - if (!info.m_bookingDatafileName.empty()) - { - bookingDataset.BuildFeatures([&](OsmElement * e) { parser.EmitElement(e); }); - LOG(LINFO, ("Processing booking data from", info.m_bookingDatafileName, "done.")); - string skippedElementsPath = info.GetIntermediateFileName("skipped_elements", ".lst"); - ofstream file(skippedElementsPath); - if (file.is_open()) - { - file << skippedElements.str(); - LOG(LINFO, ("Saving skipped elements to", skippedElementsPath, "done.")); - } - else - { - LOG(LERROR, ("Can't output into", skippedElementsPath)); - } - } + // TOFO(mgsergio): Build features in Emitter. + // if (!info.m_bookingDatafileName.empty()) + // { + // bookingDataset.BuildFeatures([&](OsmElement * e) { parser.EmitElement(e); }); + // LOG(LINFO, ("Processing booking data from", info.m_bookingDatafileName, "done.")); + // string skippedElementsPath = info.GetIntermediateFileName("skipped_elements", ".lst"); + // ofstream file(skippedElementsPath); + // if (file.is_open()) + // { + // file << skippedElements.str(); + // LOG(LINFO, ("Saving skipped elements to", skippedElementsPath, "done.")); + // } + // else + // { + // LOG(LERROR, ("Can't output into", skippedElementsPath)); + // } + // } // Stop if coasts are not merged and FLAG_fail_on_coasts is set if (!emitter.Finish()) |