diff --git a/sources.cmake b/sources.cmake index f626ee681..e53d72d15 100644 --- a/sources.cmake +++ b/sources.cmake @@ -173,6 +173,7 @@ src/network/types.cpp src/online/current_user.cpp src/online/http_manager.cpp src/online/messages.cpp +src/online/profile.cpp src/online/profile_manager.cpp src/online/request.cpp src/online/server.cpp @@ -469,6 +470,7 @@ src/network/types.hpp src/online/current_user.hpp src/online/http_manager.hpp src/online/messages.hpp +src/online/profile.hpp src/online/profile_manager.hpp src/online/request.hpp src/online/server.hpp diff --git a/src/online/current_user.cpp b/src/online/current_user.cpp index 1d11e5ce2..5829ede7b 100644 --- a/src/online/current_user.cpp +++ b/src/online/current_user.cpp @@ -219,9 +219,9 @@ namespace Online{ } // ============================================================================ - const ProfileManager::FriendsListRequest * CurrentUser::requestFriendsOf(const uint32_t visiting_id){ + const Profile::FriendsListRequest * CurrentUser::requestFriendsOf(const uint32_t visiting_id){ assert(isRegisteredUser()); - ProfileManager::FriendsListRequest * request = new ProfileManager::FriendsListRequest(); + Profile::FriendsListRequest * request = new Profile::FriendsListRequest(); request->setURL((std::string)UserConfigParams::m_server_multiplayer + "client-user.php"); request->setParameter("action",std::string("get-friends-list")); request->setParameter("token", getToken()); diff --git a/src/online/current_user.hpp b/src/online/current_user.hpp index 240378e86..d51dda35e 100644 --- a/src/online/current_user.hpp +++ b/src/online/current_user.hpp @@ -22,7 +22,7 @@ #include "http_manager.hpp" #include "online/server.hpp" #include "online/user.hpp" -#include "online/profile_manager.hpp" +#include "online/profile.hpp" #include "utils/types.hpp" #include "utils/synchronised.hpp" @@ -140,7 +140,7 @@ namespace Online{ const setAddonVoteRequest * requestSetAddonVote(const std::string & addon_id, float rating) const; - const ProfileManager::FriendsListRequest * requestFriendsOf(const uint32_t visiting_id); + const Profile::FriendsListRequest * requestFriendsOf(const uint32_t visiting_id); /** Returns the username if signed in. */ const irr::core::stringw getUserName() const; diff --git a/src/online/profile.cpp b/src/online/profile.cpp new file mode 100644 index 000000000..761943d2a --- /dev/null +++ b/src/online/profile.cpp @@ -0,0 +1,97 @@ +// +// SuperTuxKart - a fun racing game with go-kart +// Copyright (C) 2013 Glenn De Jonghe +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 3 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + +#include "online/profile.hpp" + +#include "online/profile_manager.hpp" +#include "online/current_user.hpp" +#include "utils/log.hpp" +#include "utils/translation.hpp" + +#include +#include +#include + +using namespace Online; + +namespace Online{ + + + // ============================================================================ + Profile::Profile(User * user) + { + setState (S_READY); + m_is_current_user = false; + m_cache_bit = false; + m_id = user->getUserID(); + m_username = user->getUserName(); + m_is_current_user = (m_id == CurrentUser::get()->getUserID()); + + m_has_fetched_friends = false; + m_friends_list_request = NULL; + + } + + // ============================================================================ + void Profile::fetchFriends() + { + assert(CurrentUser::get()->isRegisteredUser()); + if(m_has_fetched_friends) + return; + setState (S_FETCHING); + m_friends_list_request = CurrentUser::get()->requestFriendsOf(m_id); + } + // ============================================================================ + + + void Profile::friendsListCallback(const XMLNode * input) + { + uint32_t friendid = 0; + irr::core::stringw username(""); + const XMLNode * friends_xml = input->getNode("friends"); + m_friends.clearAndDeleteAll(); + for (unsigned int i = 0; i < friends_xml->getNumNodes(); i++) + { + friends_xml->getNode(i)->get("friend_id", &friendid); + m_friends.push_back(new User(username, friendid)); + } + Profile::setState (Profile::S_READY); + } + + + // ============================================================================ + + void Profile::FriendsListRequest::callback() + { + uint32_t user_id; + m_result->get("visitingid", &user_id); + assert(ProfileManager::get()->getProfileByID(user_id) != NULL); + ProfileManager::get()->getProfileByID(user_id)->friendsListCallback(m_result); + } + + // ============================================================================ + + const PtrVector & Profile::getFriends() + { + assert (m_has_fetched_friends && getState() == S_READY); + return m_friends; + } + // ============================================================================ + +} // namespace Online diff --git a/src/online/profile.hpp b/src/online/profile.hpp new file mode 100644 index 000000000..2e4b581af --- /dev/null +++ b/src/online/profile.hpp @@ -0,0 +1,97 @@ +// +// SuperTuxKart - a fun racing game with go-kart +// Copyright (C) 2013 Glenn De Jonghe +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 3 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#ifndef HEADER_ONLINE_PROFILE_HPP +#define HEADER_ONLINE_PROFILE_HPP + +#include "http_manager.hpp" +#include "online/request.hpp" +#include "online/user.hpp" +#include "utils/types.hpp" +#include "utils/ptr_vector.hpp" + + +#include + +#include + +namespace Online{ + + // ============================================================================ + + /** + * \brief Class that represents an online profile + * \ingroup online + */ + class Profile + { + public : + class FriendsListRequest : public XMLRequest + { + virtual void callback (); + public: + FriendsListRequest() : XMLRequest() {} + }; + private: + + enum State + { + S_FETCHING = 1, + S_READY + }; + + Synchronised m_state; + bool m_is_current_user; + uint32_t m_id; + irr::core::stringw m_username; + + bool m_has_fetched_friends; + PtrVector m_friends; + const FriendsListRequest * m_friends_list_request; + + bool m_cache_bit; + + + + void setState(State state) { m_state.setAtomic(state); } + const State getState() const { return m_state.getAtomic(); } + + void friendsListCallback(const XMLNode * input); + + public: + Profile(User * user); + void fetchFriends(); + const PtrVector & getFriends(); + + bool isFetching() { return getState() == S_FETCHING; } + bool isReady() { return getState() == S_READY; } + + void setCacheBit() { m_cache_bit = true; } + void unsetCacheBit() { m_cache_bit = false; } + bool getCacheBit() { return m_cache_bit; } + uint32_t getID() { return m_id; } + irr::core::stringw getUsername() { return m_username; } + + + }; // class CurrentUser + +} // namespace Online + +#endif + +/*EOF*/ diff --git a/src/online/profile_manager.cpp b/src/online/profile_manager.cpp index a6350c23b..f7f9eee9d 100644 --- a/src/online/profile_manager.cpp +++ b/src/online/profile_manager.cpp @@ -30,86 +30,101 @@ using namespace Online; namespace Online{ - static ProfileManager* current_user_singleton(NULL); + static ProfileManager* profile_manager_singleton(NULL); ProfileManager* ProfileManager::get() { - if (current_user_singleton == NULL) - current_user_singleton = new ProfileManager(); - return current_user_singleton; + if (profile_manager_singleton == NULL) + profile_manager_singleton = new ProfileManager(); + return profile_manager_singleton; } void ProfileManager::deallocate() { - delete current_user_singleton; - current_user_singleton = NULL; + delete profile_manager_singleton; + profile_manager_singleton = NULL; } // deallocate // ============================================================================ ProfileManager::ProfileManager() { - setState (S_READY); - m_is_current_user = false; - m_has_fetched_friends = false; + assert(m_max_cache_size > 1); } // ============================================================================ - void ProfileManager::set(User * user) + + void ProfileManager::iterateCache() { - if (user == NULL) + if(m_profiles_cache.size() == m_max_cache_size) { - assert(CurrentUser::get()->isRegisteredUser()); - m_is_current_user = true; - m_visiting_id = CurrentUser::get()->getUserID(); - m_visiting_username = CurrentUser::get()->getUserName(); + m_currently_visiting->setCacheBit(); + ProfilesMap::iterator iter; + for (iter = m_profiles_cache.begin(); iter != m_profiles_cache.end(); ++iter) + { + if (!iter->second->getCacheBit()) + return; + } + //All cache bits are one! Set then all to zero except the one currently being visited + for (iter = m_profiles_cache.begin(); iter != m_profiles_cache.end(); ++iter) + { + iter->second->unsetCacheBit(); + } + m_currently_visiting->setCacheBit(); + } + + } + + // ============================================================================ + + void ProfileManager::addToCache(Profile * profile) + { + + if(m_profiles_cache.size() == m_max_cache_size) + { + ProfilesMap::iterator iter; + for (iter = m_profiles_cache.begin(); iter != m_profiles_cache.end();) + { + if (!iter->second->getCacheBit()) + { + m_profiles_cache.erase(iter++); + continue; + } + else + ++iter; + } + } + m_profiles_cache[profile->getID()] = profile; + assert(m_profiles_cache.size() <= m_max_cache_size); + + } + + // ============================================================================ + void ProfileManager::setVisiting(User * user) + { + assert(user != NULL); + if( m_profiles_cache.find(user->getUserID()) == m_profiles_cache.end()) + { + //cache miss + m_currently_visiting = new Profile(user); + addToCache(m_currently_visiting); } else { - m_is_current_user = false; - m_visiting_id = CurrentUser::get()->getUserID(); + //cache hit + m_currently_visiting = m_profiles_cache[user->getUserID()]; } + iterateCache(); } // ============================================================================ - void ProfileManager::fetchFriends() + + Profile * ProfileManager::getProfileByID(uint32_t id) { - if(m_has_fetched_friends) - return; - //m_friends_list_request - setState (S_FETCHING); - } - // ============================================================================ - - - void ProfileManager::friendsListCallback(const XMLNode * input) - { - uint32_t friendid = 0; - irr::core::stringw username(""); - const XMLNode * friends_xml = input->getNode("friends"); - m_friends.clearAndDeleteAll(); - for (unsigned int i = 0; i < friends_xml->getNumNodes(); i++) - { - friends_xml->getNode(i)->get("friend_id", &friendid); - m_friends.push_back(new User(username, friendid)); - } - ProfileManager::setState (ProfileManager::S_READY); + if( m_profiles_cache.find(id) == m_profiles_cache.end()) + return NULL; + return m_profiles_cache[id]; } - // ============================================================================ - - void ProfileManager::FriendsListRequest::callback() - { - ProfileManager::get()->friendsListCallback(m_result); - } - - // ============================================================================ - - const PtrVector & ProfileManager::getFriends() - { - assert (m_has_fetched_friends && getState() == S_READY); - return m_friends; - } - // ============================================================================ } // namespace Online diff --git a/src/online/profile_manager.hpp b/src/online/profile_manager.hpp index 34d0a15d9..985be11b3 100644 --- a/src/online/profile_manager.hpp +++ b/src/online/profile_manager.hpp @@ -19,11 +19,9 @@ #ifndef HEADER_ONLINE_PROFILE_MANAGER_HPP #define HEADER_ONLINE_PROFILE_MANAGER_HPP -#include "http_manager.hpp" -#include "online/request.hpp" #include "online/user.hpp" #include "utils/types.hpp" -#include "utils/ptr_vector.hpp" +#include "online/profile.hpp" #include @@ -40,13 +38,7 @@ namespace Online{ */ class ProfileManager { - public : - class FriendsListRequest : public XMLRequest - { - virtual void callback (); - public: - FriendsListRequest() : XMLRequest() {} - }; + private: ProfileManager (); @@ -56,34 +48,23 @@ namespace Online{ S_READY }; - Synchronised m_state; - bool m_is_current_user; - uint32_t m_visiting_id; - irr::core::stringw m_visiting_username; + typedef std::map ProfilesMap; - bool m_has_fetched_friends; - PtrVector m_friends; - FriendsListRequest * m_friends_list_request; + ProfilesMap m_profiles_cache; + Profile * m_currently_visiting; + const int m_max_cache_size = 5; - - - void setState(State state) { m_state.setAtomic(state); } - const State getState() const { return m_state.getAtomic(); } - - void friendsListCallback(const XMLNode * input); + void iterateCache(); + void addToCache(Profile * profile); public: /**Singleton */ - static ProfileManager * get(); - static void deallocate(); - - void set(Online::User * = NULL); - void fetchFriends(); - const PtrVector & getFriends(); - - bool isFetching() { return getState() == S_FETCHING; } - bool isReady() { return getState() == S_READY; } + static ProfileManager * get(); + static void deallocate(); + void setVisiting(Online::User * user); + Profile * getVisitingProfile() {return m_currently_visiting;} + Profile * getProfileByID(uint32_t id); }; // class CurrentUser