Skip to content

Commit

Permalink
Merge pull request #5455 from ygorshenin/extend-hotels-filtering
Browse files Browse the repository at this point in the history
[search] Added filtering by hotel type.
  • Loading branch information
bykoianko committed Feb 22, 2017
2 parents c467bea + f62143c commit 36f7f7c
Show file tree
Hide file tree
Showing 7 changed files with 186 additions and 33 deletions.
68 changes: 61 additions & 7 deletions indexer/ftypes_matcher.cpp
@@ -1,8 +1,11 @@
#include "indexer/ftypes_matcher.hpp"

#include "indexer/classificator.hpp"
#include "indexer/feature.hpp"
#include "indexer/feature_data.hpp"
#include "indexer/classificator.hpp"

#include "base/assert.hpp"
#include "base/buffer_vector.hpp"

#include <algorithm>
#include <map>
Expand Down Expand Up @@ -373,8 +376,19 @@ IsBookingChecker const & IsBookingChecker::Instance()
IsHotelChecker::IsHotelChecker()
{
Classificator const & c = classif();
for (auto const & tag : GetHotelTags())
m_types.push_back(c.GetTypeByPath({"tourism", tag}));
for (size_t i = 0; i < static_cast<size_t>(Type::Count); ++i)
{
auto const hotelType = static_cast<Type>(i);
auto const * const tag = GetHotelTypeTag(hotelType);
auto const type = c.GetTypeByPath({"tourism", tag});

m_types.push_back(type);

m_sortedTypes[i].first = type;
m_sortedTypes[i].second = hotelType;
}

sort(m_sortedTypes.begin(), m_sortedTypes.end());
}

IsHotelChecker const & IsHotelChecker::Instance()
Expand All @@ -383,11 +397,51 @@ IsHotelChecker const & IsHotelChecker::Instance()
return inst;
}

vector<string> const & IsHotelChecker::GetHotelTags()
unsigned IsHotelChecker::GetHotelTypesMask(FeatureType const & ft) const
{
feature::TypesHolder types(ft);
buffer_vector<uint32_t, feature::kMaxTypesCount> sortedTypes(types.begin(), types.end());
sort(sortedTypes.begin(), sortedTypes.end());

unsigned mask = 0;
size_t i = 0;
size_t j = 0;
while (i < sortedTypes.size() && j < m_sortedTypes.size())
{
if (sortedTypes[i] < m_sortedTypes[j].first)
{
++i;
}
else if (sortedTypes[i] > m_sortedTypes[j].first)
{
++j;
}
else
{
mask |= 1U << static_cast<unsigned>(m_sortedTypes[j].second);
++i;
++j;
}
}

return mask;
}

// static
char const * const IsHotelChecker::GetHotelTypeTag(Type type)
{
static vector<string> hotelTags = {"hotel", "apartment", "camp_site", "chalet",
"guest_house", "hostel", "motel", "resort"};
return hotelTags;
switch (type)
{
case Type::Hotel: return "hotel";
case Type::Apartment: return "apartment";
case Type::CampSite: return "camp_site";
case Type::Chalet: return "chalet";
case Type::GuestHouse: return "guest_house";
case Type::Hostel: return "hostel";
case Type::Motel: return "motel";
case Type::Resort: return "resort";
case Type::Count: CHECK(false, ("Can't get hotel type tag")); return "";
}
}

IsWifiChecker::IsWifiChecker()
Expand Down
31 changes: 28 additions & 3 deletions indexer/ftypes_matcher.hpp
Expand Up @@ -3,7 +3,9 @@
#include "base/base.hpp"

#include "std/algorithm.hpp"
#include "std/array.hpp"
#include "std/initializer_list.hpp"
#include "std/limits.hpp"
#include "std/string.hpp"
#include "std/utility.hpp"
#include "std/vector.hpp"
Expand Down Expand Up @@ -160,11 +162,34 @@ class IsBookingChecker : public BaseChecker

class IsHotelChecker : public BaseChecker
{
IsHotelChecker();

public:
enum class Type
{
Hotel,
Apartment,
CampSite,
Chalet,
GuestHouse,
Hostel,
Motel,
Resort,

Count
};

static_assert(static_cast<size_t>(Type::Count) <= CHAR_BIT * sizeof(unsigned),
"Too many types of hotels");

static IsHotelChecker const & Instance();
static vector<string> const & GetHotelTags();

static char const * const GetHotelTypeTag(Type type);

unsigned GetHotelTypesMask(FeatureType const & ft) const;

private:
IsHotelChecker();

array<pair<uint32_t, Type>, static_cast<size_t>(Type::Count)> m_sortedTypes;
};

// WiFi is a type in classificator.txt,
Expand Down
3 changes: 3 additions & 0 deletions search/hotels_filter.cpp
Expand Up @@ -2,6 +2,7 @@

#include "indexer/feature.hpp"
#include "indexer/feature_meta.hpp"
#include "indexer/ftypes_matcher.hpp"

#include "base/assert.hpp"

Expand Down Expand Up @@ -40,6 +41,8 @@ void Description::FromFeature(FeatureType & ft)
if (strings::to_int(priceRate, pr))
m_priceRate = pr;
}

m_types = ftypes::IsHotelChecker::Instance().GetHotelTypesMask(ft);
}

// Rule --------------------------------------------------------------------------------------------
Expand Down
54 changes: 49 additions & 5 deletions search/hotels_filter.hpp
Expand Up @@ -4,10 +4,12 @@
#include "search/cbv.hpp"
#include "search/mwm_context.hpp"

#include "indexer/ftypes_matcher.hpp"
#include "indexer/mwm_set.hpp"

#include "std/map.hpp"
#include "std/shared_ptr.hpp"
#include "std/sstream.hpp"
#include "std/string.hpp"
#include "std/unique_ptr.hpp"
#include "std/utility.hpp"
Expand Down Expand Up @@ -63,6 +65,7 @@ struct Description

Rating::Value m_rating = Rating::kDefault;
PriceRate::Value m_priceRate = PriceRate::kDefault;
unsigned m_types = 0;
};

struct Rule
Expand All @@ -83,7 +86,7 @@ struct EqRule final : public Rule
{
using Value = typename Field::Value;

EqRule(Value value) : m_value(value) {}
explicit EqRule(Value value) : m_value(value) {}

// Rule overrides:
bool Matches(Description const & d) const override
Expand Down Expand Up @@ -112,7 +115,7 @@ struct LtRule final : public Rule
{
using Value = typename Field::Value;

LtRule(Value value) : m_value(value) {}
explicit LtRule(Value value) : m_value(value) {}

// Rule overrides:
bool Matches(Description const & d) const override
Expand Down Expand Up @@ -141,7 +144,7 @@ struct LeRule final : public Rule
{
using Value = typename Field::Value;

LeRule(Value value) : m_value(value) {}
explicit LeRule(Value value) : m_value(value) {}

// Rule overrides:
bool Matches(Description const & d) const override
Expand Down Expand Up @@ -171,7 +174,7 @@ struct GtRule final : public Rule
{
using Value = typename Field::Value;

GtRule(Value value) : m_value(value) {}
explicit GtRule(Value value) : m_value(value) {}

// Rule overrides:
bool Matches(Description const & d) const override
Expand Down Expand Up @@ -200,7 +203,7 @@ struct GeRule final : public Rule
{
using Value = typename Field::Value;

GeRule(Value value) : m_value(value) {}
explicit GeRule(Value value) : m_value(value) {}

// Rule overrides:
bool Matches(Description const & d) const override
Expand Down Expand Up @@ -297,6 +300,39 @@ struct OrRule final : public Rule
shared_ptr<Rule> m_rhs;
};

struct OneOfRule final : public Rule
{
explicit OneOfRule(unsigned types) : m_types(types) {}

// Rule overrides:
bool Matches(Description const & d) const override { return (d.m_types & m_types) != 0; }

bool IdenticalTo(Rule const & rhs) const override
{
auto const * r = dynamic_cast<OneOfRule const *>(&rhs);
return r && m_types == r->m_types;
}

string ToString() const override
{
ostringstream os;
os << "[ one of:";
for (size_t i = 0; i < static_cast<size_t>(ftypes::IsHotelChecker::Type::Count); ++i)
{
unsigned const bit = 1U << i;
if ((m_types & bit) == 0)
continue;

auto const type = static_cast<ftypes::IsHotelChecker::Type>(i);
os << " " << ftypes::IsHotelChecker::GetHotelTypeTag(type);
}
os << " ]";
return os.str();
}

unsigned m_types;
};

template <typename Field>
shared_ptr<Rule> Eq(typename Field::Value value)
{
Expand Down Expand Up @@ -337,6 +373,14 @@ inline shared_ptr<Rule> Or(shared_ptr<Rule> lhs, shared_ptr<Rule> rhs)
return make_shared<OrRule>(lhs, rhs);
}

inline shared_ptr<Rule> Is(ftypes::IsHotelChecker::Type type)
{
CHECK(type != ftypes::IsHotelChecker::Type::Count, ());
return make_shared<OneOfRule>(1U << static_cast<unsigned>(type));
}

inline shared_ptr<Rule> OneOf(unsigned types) { return make_shared<OneOfRule>(types); }

class HotelsFilter
{
public:
Expand Down
7 changes: 7 additions & 0 deletions search/search_integration_tests/helpers.cpp
Expand Up @@ -72,6 +72,13 @@ bool SearchTest::ResultsMatch(vector<search::Result> const & results, TRules con
return MatchResults(m_engine, rules, results);
}

bool SearchTest::ResultsMatch(SearchParams const & params, TRules const & rules)
{
tests_support::TestSearchRequest request(m_engine, params, m_viewport);
request.Run();
return ResultsMatch(request.Results(), rules);
}

unique_ptr<tests_support::TestSearchRequest> SearchTest::MakeRequest(string const & query)
{
SearchParams params;
Expand Down
2 changes: 2 additions & 0 deletions search/search_integration_tests/helpers.hpp
Expand Up @@ -111,6 +111,8 @@ class SearchTest : public TestWithClassificator

bool ResultsMatch(vector<search::Result> const & results, TRules const & rules);

bool ResultsMatch(SearchParams const & params, TRules const & rules);

unique_ptr<tests_support::TestSearchRequest> MakeRequest(string const & query);

size_t CountFeatures(m2::RectD const & rect);
Expand Down

0 comments on commit 36f7f7c

Please sign in to comment.