Use NewType for bookingid.

This commit is contained in:
Sergey Magidovich 2016-08-23 15:03:00 +03:00
parent 569ea6f284
commit 78ea6a4038
4 changed files with 36 additions and 29 deletions

View file

@ -36,13 +36,15 @@ string EscapeTabs(string const & str)
}
} // namespace
BookingDataset::BookingId const BookingDataset::kInvalidHotelIndex = BookingId(numeric_limits<BookingId::RepType>::max());
BookingDataset::Hotel::Hotel(string const & src)
{
vector<string> rec;
strings::ParseCSVRow(src, '\t', rec);
CHECK(rec.size() == FieldsCount(), ("Error parsing hotels.tsv line:", EscapeTabs(src)));
strings::to_uint(rec[Index(Fields::Id)], id);
strings::to_uint(rec[Index(Fields::Id)], id.Get());
strings::to_double(rec[Index(Fields::Latitude)], lat);
strings::to_double(rec[Index(Fields::Longtitude)], lon);
@ -120,7 +122,7 @@ BookingDataset::BookingDataset(istream & dataSource, string const & addressRefer
LoadHotels(dataSource, addressReferencePath);
}
size_t BookingDataset::GetMatchingHotelIndex(FeatureBuilder1 const & fb) const
BookingDataset::BookingId BookingDataset::GetMatchingHotelId(FeatureBuilder1 const & fb) const
{
if (CanBeBooking(fb))
return MatchWithBooking(fb);
@ -135,26 +137,27 @@ bool BookingDataset::CanBeBooking(FeatureBuilder1 const & fb) const
return ftypes::IsHotelChecker::Instance()(fb.GetTypes());
}
BookingDataset::Hotel const & BookingDataset::GetHotelById(uint32_t const id) const
BookingDataset::Hotel const & BookingDataset::GetHotelById(BookingId const id) const
{
auto const it = m_hotels.find(id);
CHECK(it != end(m_hotels), ("Got wrong hotel id:", id));
return it->second;
}
BookingDataset::Hotel & BookingDataset::GetHotelById(uint32_t const id)
BookingDataset::Hotel & BookingDataset::GetHotelById(BookingId const id)
{
auto it = m_hotels.find(id);
CHECK(it != end(m_hotels), ("Got wrong hotel id:", id));
return it->second;
}
vector<uint32_t> BookingDataset::GetNearestHotels(ms::LatLon const & latLon, size_t const limit,
double const maxDistance /* = 0.0 */) const
vector<BookingDataset::BookingId> BookingDataset::GetNearestHotels(
ms::LatLon const & latLon, size_t const limit,
double const maxDistance /* = 0.0 */) const
{
namespace bgi = boost::geometry::index;
vector<uint32_t> indexes;
vector<BookingId> indexes;
for_each(bgi::qbegin(m_rtree, bgi::nearest(TPoint(latLon.lat, latLon.lon), limit)),
bgi::qend(m_rtree), [this, &latLon, &indexes, maxDistance](TValue const & v)
{
@ -184,7 +187,7 @@ void BookingDataset::BuildHotel(Hotel const & hotel,
fb.SetCenter(MercatorBounds::FromLatLon(hotel.lat, hotel.lon));
auto & metadata = params.GetMetadata();
metadata.Set(feature::Metadata::FMD_SPONSORED_ID, strings::to_string(hotel.id));
metadata.Set(feature::Metadata::FMD_SPONSORED_ID, strings::to_string(hotel.id.Get()));
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));
@ -318,18 +321,18 @@ void BookingDataset::LoadHotels(istream & src, string const & addressReferencePa
}
}
size_t BookingDataset::MatchWithBooking(FeatureBuilder1 const & fb) const
BookingDataset::BookingId BookingDataset::MatchWithBooking(FeatureBuilder1 const & fb) const
{
auto const name = fb.GetName(StringUtf8Multilang::kDefaultCode);
if (name.empty())
return false;
return kInvalidHotelIndex;
// Find |kMaxSelectedElements| nearest values to a point.
auto const bookingIndexes = GetNearestHotels(MercatorBounds::ToLatLon(fb.GetKeyPoint()),
kMaxSelectedElements, kDistanceLimitInMeters);
for (uint32_t const j : bookingIndexes)
for (auto const j : bookingIndexes)
{
if (booking_scoring::Match(GetHotelById(j), fb).IsMatched())
return j;

View file

@ -4,6 +4,8 @@
#include "search/reverse_geocoder.hpp"
#include "base/newtype.hpp"
#include "boost/geometry.hpp"
#include "boost/geometry/geometries/point.hpp"
#include "boost/geometry/geometries/box.hpp"
@ -21,9 +23,11 @@ namespace generator
class BookingDataset
{
public:
NEWTYPE(uint32_t, BookingId);
static double constexpr kDistanceLimitInMeters = 150;
static size_t constexpr kMaxSelectedElements = 3;
static auto constexpr kInvalidHotelIndex = numeric_limits<uint32_t>::max();
static BookingId const kInvalidHotelIndex;
struct Hotel
{
@ -45,8 +49,7 @@ public:
Counter
};
// TODO(mgsergio): Make a separate type for this or an alias.
uint32_t id = 0;
BookingId id{kInvalidHotelIndex};
double lat = 0.0;
double lon = 0.0;
string name;
@ -81,26 +84,26 @@ public:
explicit BookingDataset(string const & dataPath, string const & addressReferencePath = string());
explicit BookingDataset(istream & dataSource, string const & addressReferencePath = string());
/// @return an index of a matched hotel or kInvalidHotelIndex on failure.
size_t GetMatchingHotelIndex(FeatureBuilder1 const & fb) const;
/// @return an id of a matched hotel or kInvalidHotelIndex on failure.
BookingId GetMatchingHotelId(FeatureBuilder1 const & fb) const;
/// @return true if |fb| is a hotel with a name.
bool CanBeBooking(FeatureBuilder1 const & fb) const;
inline size_t Size() const { return m_hotels.size(); }
Hotel const & GetHotelById(uint32_t id) const;
Hotel & GetHotelById(uint32_t id);
vector<uint32_t> GetNearestHotels(ms::LatLon const & latLon, size_t limit,
double maxDistance = 0.0) const;
Hotel const & GetHotelById(BookingId id) const;
Hotel & GetHotelById(BookingId id);
vector<BookingId> GetNearestHotels(ms::LatLon const & latLon, size_t limit,
double maxDistance = 0.0) const;
bool MatchByName(string const & osmName, vector<size_t> const & bookingIndexes) const;
void BuildHotels(function<void(FeatureBuilder1 &)> const & fn) const;
protected:
map<uint32_t, Hotel> m_hotels;
map<BookingId, Hotel> m_hotels;
using TPoint = boost::geometry::model::point<float, 2, boost::geometry::cs::cartesian>;
using TBox = boost::geometry::model::box<TPoint>;
using TValue = pair<TBox, uint32_t>;
using TValue = pair<TBox, BookingId>;
// Create the rtree using default constructor.
boost::geometry::index::rtree<TValue, boost::geometry::index::quadratic<16>> m_rtree;
@ -108,9 +111,11 @@ protected:
void BuildHotel(Hotel const & hotel, function<void(FeatureBuilder1 &)> const & fn) const;
void LoadHotels(istream & path, string const & addressReferencePath);
/// @return an index of a matched hotel or numeric_limits<size_t>::max() on failure.
size_t MatchWithBooking(FeatureBuilder1 const & e) const;
/// @return an id of a matched hotel or kInvalidHotelIndex on failure.
BookingId MatchWithBooking(FeatureBuilder1 const & e) const;
};
ostream & operator<<(ostream & s, BookingDataset::Hotel const & h);
NEWTYPE_SIMPLE_OUTPUT(BookingDataset::BookingId);
} // namespace generator

View file

@ -139,10 +139,11 @@ feature::GenerateInfo GetGenerateInfo()
struct SampleItem
{
enum MatchStatus {Uninitialized, Yes, No};
using BookingId = BookingDataset::BookingID;
SampleItem() = default;
SampleItem(osm::Id const & osmId, uint32_t const bookingId, MatchStatus const match = Uninitialized)
SampleItem(osm::Id const & osmId, BookingId const bookingId, MatchStatus const match = Uninitialized)
: m_osmId(osmId)
, m_bookingId(bookingId)
, m_match(match)
@ -150,7 +151,7 @@ struct SampleItem
}
osm::Id m_osmId;
uint32_t m_bookingId = BookingDataset::kInvalidHotelIndex;
BookingId m_bookingId = BookingDataset::kInvalidHotelIndex;
MatchStatus m_match = Uninitialized;
};

View file

@ -342,8 +342,6 @@ public:
static uint32_t const placeType = classif().GetTypeByPath({"place"});
uint32_t const type = fb.GetParams().FindType(placeType, 1);
auto hotelIndex = generator::BookingDataset::kInvalidHotelIndex;
if (type != ftype::GetEmptyValue() && !fb.GetName().empty())
{
m_places.ReplaceEqualInRect(
@ -351,7 +349,7 @@ 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)) !=
else if (m_bookingDataset.GetMatchingHotelId(fb) !=
generator::BookingDataset::kInvalidHotelIndex)
{
m_skippedElements << DebugPrint(fb.GetMostGenericOsmId()) << endl;