gui/dialogs/lobby/lobby_info.cpp

Go to the documentation of this file.
00001 /* $Id: lobby_info.cpp 52533 2012-01-07 02:35:17Z shadowmaster $ */
00002 /*
00003    Copyright (C) 2009 - 2012 by Tomasz Sniatowski <kailoran@gmail.com>
00004    Part of the Battle for Wesnoth Project http://www.wesnoth.org/
00005 
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License as published by
00008    the Free Software Foundation; either version 2 of the License, or
00009    (at your option) any later version.
00010    This program is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY.
00012 
00013    See the COPYING file for more details.
00014 */
00015 
00016 #include "gui/dialogs/lobby/lobby_info.hpp"
00017 
00018 #include "config.hpp"
00019 #include "game_preferences.hpp"
00020 #include "filesystem.hpp"
00021 #include "foreach.hpp"
00022 #include "formula_string_utils.hpp"
00023 #include "gettext.hpp"
00024 #include "network.hpp"
00025 #include "log.hpp"
00026 #include "map.hpp"
00027 #include "map_exception.hpp"
00028 #include "wml_exception.hpp"
00029 
00030 #include <iterator>
00031 
00032 static lg::log_domain log_config("config");
00033 #define ERR_CF LOG_STREAM(err, log_config)
00034 static lg::log_domain log_engine("engine");
00035 #define WRN_NG LOG_STREAM(warn, log_engine)
00036 
00037 static lg::log_domain log_lobby("lobby");
00038 #define DBG_LB LOG_STREAM(debug, log_lobby)
00039 #define LOG_LB LOG_STREAM(info, log_lobby)
00040 #define WRN_LB LOG_STREAM(warn, log_lobby)
00041 #define ERR_LB LOG_STREAM(err, log_lobby)
00042 #define SCOPE_LB log_scope2(log_lobby, __func__)
00043 
00044 
00045 lobby_info::lobby_info(const config& game_config)
00046     : game_config_(game_config)
00047     , gamelist_()
00048     , gamelist_initialized_(false)
00049     , rooms_()
00050     , games_by_id_()
00051     , games_()
00052     , games_filtered_()
00053     , users_()
00054     , users_sorted_()
00055     , whispers_()
00056     , game_filter_()
00057     , game_filter_invert_(false)
00058     , games_visibility_()
00059 {
00060 }
00061 
00062 lobby_info::~lobby_info()
00063 {
00064     delete_games();
00065 }
00066 
00067 void lobby_info::delete_games()
00068 {
00069     foreach (const game_info_map::value_type& v, games_by_id_) {
00070         delete v.second;
00071     }
00072 }
00073 
00074 namespace {
00075 
00076 std::string dump_games_map(const lobby_info::game_info_map& games)
00077 {
00078     std::stringstream ss;
00079     foreach (const lobby_info::game_info_map::value_type& v, games) {
00080         const game_info& game = *v.second;
00081         ss << "G" << game.id << "(" << game.name << ") " << game.display_status_string() << " ";
00082     }
00083     ss << "\n";
00084     return ss.str();
00085 }
00086 
00087 std::string dump_games_config(const config& gamelist)
00088 {
00089     std::stringstream ss;
00090     foreach (const config& c, gamelist.child_range("game")) {
00091         ss << "g" << c["id"] << "(" << c["name"] << ") " << c[config::diff_track_attribute] << " ";
00092     }
00093     ss << "\n";
00094     return ss.str();
00095 }
00096 
00097 } //end anonymous namespace
00098 
00099 void lobby_info::process_gamelist(const config &data)
00100 {
00101     SCOPE_LB;
00102     gamelist_ = data;
00103     gamelist_initialized_ = true;
00104     delete_games();
00105     games_by_id_.clear();
00106     foreach (const config& c, gamelist_.child("gamelist").child_range("game")) {
00107         game_info* game = new game_info(c, game_config_);
00108         games_by_id_[game->id] = game;
00109     }
00110     DBG_LB << dump_games_map(games_by_id_);
00111     DBG_LB << dump_games_config(gamelist_.child("gamelist"));
00112     process_userlist();
00113 }
00114 
00115 
00116 bool lobby_info::process_gamelist_diff(const config &data)
00117 {
00118     SCOPE_LB;
00119     if (!gamelist_initialized_) return false;
00120     DBG_LB << "prediff " << dump_games_config(gamelist_.child("gamelist"));
00121     try {
00122         gamelist_.apply_diff(data, true);
00123     } catch(config::error& e) {
00124         ERR_LB << "Error while applying the gamelist diff: '"
00125             << e.message << "' Getting a new gamelist.\n";
00126         network::send_data(config("refresh_lobby"), 0);
00127         return false;
00128     }
00129     DBG_LB << "postdiff " << dump_games_config(gamelist_.child("gamelist"));
00130     DBG_LB << dump_games_map(games_by_id_);
00131     config::child_itors range = gamelist_.child("gamelist").child_range("game");
00132     for (config::child_iterator i = range.first; i != range.second; ++i) {
00133         config& c = *i;
00134         DBG_LB << "data process: " << c["id"] << " (" << c[config::diff_track_attribute] << ")\n";
00135         int game_id = c["id"];
00136         if (game_id == 0) {
00137             ERR_LB << "game with id 0 in gamelist config\n";
00138             network::send_data(config("refresh_lobby"), 0);
00139             return false;
00140         }
00141         game_info_map::iterator current_i = games_by_id_.find(game_id);
00142         const std::string& diff_result = c[config::diff_track_attribute];
00143         if (diff_result == "new" || diff_result == "modified") {
00144             if (current_i == games_by_id_.end()) {
00145                 games_by_id_.insert(std::make_pair(game_id, new game_info(c, game_config_)));
00146             } else {
00147                 //had a game with that id, so update it and mark it as such
00148                 *(current_i->second) = game_info(c, game_config_);
00149                 current_i->second->display_status = game_info::UPDATED;
00150             }
00151         } else if (diff_result == "deleted") {
00152             if (current_i == games_by_id_.end()) {
00153                 WRN_LB << "Would have to delete a game that I don't have: " << game_id << "\n";
00154             } else {
00155                 if (current_i->second->display_status == game_info::NEW) {
00156                     //this means the game never made it through to the user interface
00157                     //so just deleting it is fine
00158                     games_by_id_.erase(current_i);
00159                 } else {
00160                     current_i->second->display_status = game_info::DELETED;
00161                 }
00162             }
00163         }
00164     }
00165     DBG_LB << dump_games_map(games_by_id_);
00166     try {
00167         gamelist_.clear_diff_track(data);
00168     } catch(config::error& e) {
00169         ERR_LB << "Error while applying the gamelist diff (2): '"
00170             << e.message << "' Getting a new gamelist.\n";
00171         network::send_data(config("refresh_lobby"), 0);
00172         return false;
00173     }
00174     DBG_LB << "postclean " << dump_games_config(gamelist_.child("gamelist"));
00175     process_userlist();
00176     return true;
00177 }
00178 
00179 void lobby_info::process_userlist()
00180 {
00181     SCOPE_LB;
00182     users_.clear();
00183     foreach (const config& c, gamelist_.child_range("user")) {
00184         users_.push_back(user_info(c));
00185     }
00186     foreach (user_info& ui, users_) {
00187         if (ui.game_id != 0) {
00188             game_info* g = get_game_by_id(ui.game_id);
00189             if (g == NULL) {
00190                 WRN_NG << "User " << ui.name << " has unknown game_id: " << ui.game_id << "\n";
00191             } else {
00192                 switch (ui.relation) {
00193                     case user_info::FRIEND:
00194                         g->has_friends = true;
00195                         break;
00196                     case user_info::IGNORED:
00197                         g->has_ignored = true;
00198                         break;
00199                     default:
00200                         break;
00201                 }
00202             }
00203         }
00204     }
00205 }
00206 
00207 void lobby_info::sync_games_display_status()
00208 {
00209     DBG_LB << "lobby_info::sync_games_display_status";
00210     DBG_LB << "games_by_id_ size: " << games_by_id_.size();
00211     game_info_map::iterator i = games_by_id_.begin();
00212     while (i != games_by_id_.end()) {
00213         if (i->second->display_status == game_info::DELETED) {
00214             games_by_id_.erase(i++);
00215         } else {
00216             i->second->display_status = game_info::CLEAN;
00217             ++i;
00218         }
00219     }
00220     DBG_LB << " -> " << games_by_id_.size() << "\n";
00221     make_games_vector();
00222 }
00223 
00224 game_info* lobby_info::get_game_by_id(int id)
00225 {
00226     std::map<int, game_info*>::iterator i = games_by_id_.find(id);
00227     return i == games_by_id_.end() ? NULL : i->second;
00228 }
00229 
00230 const game_info* lobby_info::get_game_by_id(int id) const
00231 {
00232     std::map<int, game_info*>::const_iterator i = games_by_id_.find(id);
00233     return i == games_by_id_.end() ? NULL : i->second;
00234 }
00235 
00236 room_info* lobby_info::get_room(const std::string &name)
00237 {
00238     foreach (room_info& r, rooms_) {
00239         if (r.name() == name) return &r;
00240     }
00241     return NULL;
00242 }
00243 
00244 const room_info* lobby_info::get_room(const std::string &name) const
00245 {
00246     foreach (const room_info& r, rooms_) {
00247         if (r.name() == name) return &r;
00248     }
00249     return NULL;
00250 }
00251 
00252 bool lobby_info::has_room(const std::string &name) const
00253 {
00254     return get_room(name) != NULL;
00255 }
00256 
00257 chat_log& lobby_info::get_whisper_log(const std::string &name)
00258 {
00259     return whispers_[name];
00260 }
00261 
00262 void lobby_info::open_room(const std::string &name)
00263 {
00264     if (!has_room(name)) {
00265         rooms_.push_back(room_info(name));
00266     }
00267 }
00268 
00269 void lobby_info::close_room(const std::string &name)
00270 {
00271     room_info* r = get_room(name);
00272     DBG_LB << "lobby info: closing room " << name
00273             << " " << static_cast<void*>(r) << "\n";
00274     if (r) {
00275         rooms_.erase(rooms_.begin() + (r - &rooms_[0]));
00276     }
00277 }
00278 
00279 const std::vector<game_info*>& lobby_info::games_filtered() const
00280 {
00281     return games_filtered_;
00282 }
00283 
00284 void lobby_info::add_game_filter(game_filter_base *f)
00285 {
00286     game_filter_.append(f);
00287 }
00288 
00289 void lobby_info::clear_game_filter()
00290 {
00291     game_filter_.clear();
00292 }
00293 
00294 void lobby_info::set_game_filter_invert(bool value)
00295 {
00296     game_filter_invert_ = value;
00297 }
00298 
00299 void lobby_info::make_games_vector()
00300 {
00301     games_filtered_.clear();
00302     games_visibility_.clear();
00303     games_.clear();
00304     foreach (const game_info_map::value_type& v, games_by_id_) {
00305         games_.push_back(v.second);
00306     }
00307 }
00308 
00309 void lobby_info::apply_game_filter()
00310 {
00311     games_filtered_.clear();
00312     games_visibility_.clear();
00313     foreach (game_info* g, games_) {
00314         game_info& gi = *g;
00315         bool show = game_filter_.match(gi);
00316         if (game_filter_invert_) {
00317             show = !show;
00318         }
00319         games_visibility_.push_back(show);
00320         if (show) {
00321             games_filtered_.push_back(&gi);
00322         }
00323     }
00324 }
00325 
00326 void lobby_info::update_user_statuses(int game_id, const room_info *room)
00327 {
00328     foreach (user_info& user, users_) {
00329         user.update_state(game_id, room);
00330     }
00331 }
00332 
00333 
00334 struct user_sorter_name
00335 {
00336     bool operator()(const user_info& u1, const user_info& u2) {
00337         return u1.name < u2.name;
00338     }
00339     bool operator()(const user_info* u1, const user_info* u2) {
00340         return operator()(*u1, *u2);
00341     }
00342 };
00343 
00344 struct user_sorter_relation
00345 {
00346     bool operator()(const user_info& u1, const user_info& u2) {
00347         return static_cast<int>(u1.relation) < static_cast<int>(u2.relation);
00348     }
00349     bool operator()(const user_info* u1, const user_info* u2) {
00350         return operator()(*u1, *u2);
00351     }
00352 };
00353 
00354 struct user_sorter_relation_name
00355 {
00356     bool operator()(const user_info& u1, const user_info& u2) {
00357         return static_cast<int>(u1.relation) < static_cast<int>(u2.relation)
00358             || (u1.relation == u2.relation && u1.name < u2.name);
00359     }
00360     bool operator()(const user_info* u1, const user_info* u2) {
00361         return operator()(*u1, *u2);
00362     }
00363 };
00364 
00365 void lobby_info::sort_users(bool by_name, bool by_relation)
00366 {
00367     users_sorted_.clear();
00368     foreach (user_info& u, users_) {
00369         users_sorted_.push_back(&u);
00370     }
00371     if (by_name) {
00372         if (by_relation) {
00373             std::sort(users_sorted_.begin(), users_sorted_.end(), user_sorter_relation_name());
00374         } else {
00375             std::sort(users_sorted_.begin(), users_sorted_.end(), user_sorter_name());
00376         }
00377     } else if (by_relation) {
00378         std::sort(users_sorted_.begin(), users_sorted_.end(), user_sorter_relation());
00379     }
00380 }
00381 
00382 const std::vector<user_info*>& lobby_info::users_sorted() const
00383 {
00384     return users_sorted_;
00385 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated by doxygen 1.7.1 on Fri May 25 2012 01:02:58 for The Battle for Wesnoth
Gna! | Forum | Wiki | CIA | devdocs