MP Lobby: refactored games filtering

This commit is contained in:
Charles Dang 2016-08-30 12:29:00 +11:00
parent 9b782931bb
commit 95a2fb3a46
5 changed files with 36 additions and 145 deletions

View file

@ -367,48 +367,12 @@ const char* game_info::display_status_string() const
}
}
game_filter_stack::game_filter_stack() : filters_()
bool game_info::match_string_filter(const std::string& filter) const
{
}
game_filter_stack::~game_filter_stack()
{
for(auto f : filters_) {
delete f;
}
}
void game_filter_stack::append(game_filter_base* f)
{
filters_.push_back(f);
}
void game_filter_stack::clear()
{
for(auto f : filters_) {
delete f;
}
filters_.clear();
}
bool game_filter_and_stack::match(const game_info& game) const
{
for(auto f : filters_) {
if(!f->match(game)) {
return false;
}
}
return true;
}
bool game_filter_general_string_part::match(const game_info& game) const
{
const std::string& s1 = game.map_info;
const std::string& s2 = game.name;
return std::search(s1.begin(), s1.end(), value_.begin(), value_.end(),
const std::string& s1 = map_info;
const std::string& s2 = name;
return std::search(s1.begin(), s1.end(), filter.begin(), filter.end(),
chars_equal_insensitive) != s1.end()
|| std::search(s2.begin(), s2.end(), value_.begin(), value_.end(),
|| std::search(s2.begin(), s2.end(), filter.begin(), filter.end(),
chars_equal_insensitive) != s2.end();
}

View file

@ -185,93 +185,8 @@ struct game_info
game_display_status display_status;
const char* display_status_string() const;
};
class game_filter_base
{
public:
virtual ~game_filter_base()
{
}
virtual bool match(const game_info& game) const = 0;
bool operator()(const game_info& game) const
{
return match(game);
}
};
template <class T>
class game_filter_not : public game_filter_base
{
public:
explicit game_filter_not(const T& t) : t(t)
{
}
bool match(const game_info& game) const
{
return !t.match(game);
}
T t;
};
class game_filter_stack : public game_filter_base
{
public:
game_filter_stack();
virtual ~game_filter_stack();
/**
* Takes ownership
*/
void append(game_filter_base* f);
void clear();
bool empty() const
{
return filters_.empty();
}
protected:
std::vector<game_filter_base*> filters_;
};
class game_filter_and_stack : public game_filter_stack
{
public:
bool match(const game_info& game) const;
};
template <class T, T game_info::*member, class OP = std::equal_to<T> >
class game_filter_value : public game_filter_base
{
public:
explicit game_filter_value(const T& value) : member_(member), value_(value)
{
}
bool match(const game_info& game) const
{
return OP()(game.*member_, value_);
}
private:
T game_info::*member_;
T value_;
};
class game_filter_general_string_part : public game_filter_base
{
public:
explicit game_filter_general_string_part(const std::string& value)
: value_(value)
{
}
bool match(const game_info& game) const;
private:
std::string value_;
bool match_string_filter(const std::string& filter) const;
};
#endif

View file

@ -46,7 +46,7 @@ lobby_info::lobby_info(const config& game_config, twesnothd_connection& wesnothd
, users_()
, users_sorted_()
, whispers_()
, game_filter_()
, game_filters_()
, game_filter_invert_(false)
, games_visibility_()
, wesnothd_connection_(wesnothd_connection)
@ -299,14 +299,14 @@ const std::vector<game_info*>& lobby_info::games_filtered() const
return games_filtered_;
}
void lobby_info::add_game_filter(game_filter_base* f)
void lobby_info::add_game_filter(game_filter_func func)
{
game_filter_.append(f);
game_filters_.push_back(func);
}
void lobby_info::clear_game_filter()
{
game_filter_.clear();
game_filters_.clear();
}
void lobby_info::set_game_filter_invert(bool value)
@ -332,7 +332,11 @@ void lobby_info::apply_game_filter()
for(auto g : games_) {
game_info& gi = *g;
bool show = game_filter_.match(gi);
bool show = true;
for(const auto& filter_func : game_filters_) {
if(!(show = filter_func(gi))) break;
}
if(game_filter_invert_) {
show = !show;
}

View file

@ -33,6 +33,8 @@ public:
typedef std::map<int, game_info*> game_info_map;
using game_filter_func = std::function<bool(const game_info&)>;
/**
* Process a full gamelist. Current info is discarded.
*/
@ -55,7 +57,7 @@ public:
}
void clear_game_filter();
void add_game_filter(game_filter_base* f);
void add_game_filter(game_filter_func func);
void set_game_filter_invert(bool value);
void apply_game_filter();
@ -110,7 +112,7 @@ private:
std::vector<user_info> users_;
std::vector<user_info*> users_sorted_;
std::map<std::string, chat_log> whispers_;
game_filter_and_stack game_filter_;
std::vector<game_filter_func> game_filters_;
bool game_filter_invert_;
std::vector<bool> games_visibility_;
twesnothd_connection& wesnothd_connection_;

View file

@ -1660,25 +1660,31 @@ void tlobby_main::game_filter_reload()
{
lobby_info_.clear_game_filter();
for(const auto & s : utils::split(filter_text_->get_value(), ' '))
{
lobby_info_.add_game_filter(new game_filter_general_string_part(s));
for(const auto& s : utils::split(filter_text_->get_value(), ' ')) {
lobby_info_.add_game_filter([s](const game_info& info)->bool {
return info.match_string_filter(s);
});
}
// TODO: make changing friend/ignore lists trigger a refresh
if(filter_friends_->get_value()) {
lobby_info_.add_game_filter(
new game_filter_value<bool, &game_info::has_friends>(true));
lobby_info_.add_game_filter([](const game_info& info)->bool {
return info.has_friends == true;
});
}
if(filter_ignored_->get_value()) {
lobby_info_.add_game_filter(
new game_filter_value<bool, &game_info::has_ignored>(false));
lobby_info_.add_game_filter([](const game_info& info)->bool {
return info.has_ignored == false;
});
}
if(filter_slots_->get_value()) {
lobby_info_.add_game_filter(
new game_filter_value<size_t,
&game_info::vacant_slots,
std::greater<size_t> >(0));
lobby_info_.add_game_filter([](const game_info& info)->bool {
return info.vacant_slots > 0;
});
}
lobby_info_.set_game_filter_invert(filter_invert_->get_value_bool());
}