#include "room.h" #include #include #include #include #include #include #include #include namespace Yc { namespace Lib { Room::Room(std::shared_ptr parent, Json::Value roomParams) : _parent(std::move(parent)), _blocked(false), _stop(false), _roundRunning(false) { _name = roomParams["name"].asString(); _password = roomParams["password"].asString(); std::vector allowedUsers; for (auto &user: roomParams["allowed"]) { _allowedUsers.push_back(user.asString()); } _type = (RoomType)roomParams["type"].asInt(); _roundLength = roomParams["roundlength"].asInt(); _lastRoundEnd = std::time(NULL); thread = std::make_unique(&Room::run, this); } Room::~Room() = default; void Room::run() { while (!_stop) { if (_msgQueue.size() > 0 && !_blocked) { _blocked = true; while (_msgQueue.size() > 0) { Message message = _msgQueue.front(); for (auto &user: _users) { user->sendMsg(message.type, message.messageTr, message.userName, message.color); } _msgQueue.pop(); } _blocked = false; } if ((_type & dice) == dice) { _handleDice(); } std::this_thread::sleep_for(std::chrono::milliseconds(50)); } } bool Room::addUser(std::string _userName, std::string color, std::string _password, int socket) { if (_password != "" && _password == _password && std::find(std::begin(_allowedUsers), std::end(_allowedUsers), _userName) == std::end(_allowedUsers)) { return false; } auto newUser = std::make_shared(shared_from_this(), _userName, color, socket); _users.push_back(newUser); newUser->sendMsg(User::roomList, _parent->jsonRoomList(), "", ""); addMessage(User::system, "room_entered", newUser->name(), newUser->color()); _initRound(); return true; } bool Room::addUser(std::shared_ptr user, std::string password) { if (password == _password) { _users.push_back(user); user->setParent(shared_from_this()); _initRound(); return true; } return false; } bool Room::userNameExists(std::string userName) { for (const auto &user: _users) { if (user->name() == userName) { return true; } } return false; } void Room::removeUser(std::string _token, bool silent) { for (auto it = _users.begin(); it != _users.end(); ++it) { if ((*it)->validateToken(_token)) { if (!silent) { addMessage(User::system, "room_exit", (*it)->name(), (*it)->color()); } _users.erase(it); break; } } } void Room::removeUser(std::shared_ptr userToRemove, bool silent) { for (auto it = _users.begin(); it != _users.end(); ++it) { if (*it == userToRemove) { if (!silent) { addMessage(User::system, "room_exit", (*it)->name(), (*it)->color()); } _users.erase(it); break; } } } void Room::setStop() { _stop = true; } void Room::addMessage(User::MsgType type, const char *messageText, std::string userName, std::string color) { addMessage(type, (std::string)messageText, userName, color); } void Room::addMessage(User::MsgType type, std::string messageText, std::string userName, std::string color) { Message message; message.type = type; message.messageTr = messageText; message.userName = userName; message.color = color; _msgQueue.push(message); } void Room::addMessage(User::MsgType type, Json::Value messageText, std::string userName, std::string color) { addMessage(type, getJsonString(messageText), userName, color); } void Room::addUserWhenQueueEmpty(std::shared_ptr user) { while (_msgQueue.size() > 0) { std::this_thread::sleep_for(std::chrono::milliseconds(100)); } _users.push_back(user); user->setParent(shared_from_this()); } bool Room::userToNewRoom(std::shared_ptr user, std::string newRoom, std::string password) { return _parent->changeRoom(user, newRoom, password); } unsigned int Room::flags() { unsigned int value = (unsigned int)_type; if (_password != "") { value += (unsigned int)Room::password; } return value; } Json::Value Room::userList() { Json::Value users = Json::arrayValue; for (auto &user: _users) { Json::Value jsonUser = Json::objectValue; jsonUser["name"] = user->name(); users.append(jsonUser); } return users; } Room::RoomType Room::type() { return _type; } bool Room::isType(Room::RoomType type) { return ((_type & type) == type); } bool Room::canDice() { return (_roundRunning || (_type & rounds) == rounds) && (_type & dice) == dice; } unsigned int Room::addDice(std::shared_ptr user, int diceValue) { if (!canDice()) { return 1; } for (auto &listUser: _diceValues) { if (listUser.first == user) { return 2; } } _diceValues.push_back(std::make_pair(user, diceValue)); addMessage(User::dice, std::to_string(diceValue), user->name(), user->color()); return 0; } bool Room::accessAllowed(std::string userName, std::string password) { return (_allowedUsers.size() == 0 || _password == "" || _password == password || std::find(_allowedUsers.begin(), _allowedUsers.end(), userName) != _allowedUsers.end()); } bool Room::userIsInRoom(std::string userName) { for (auto &user: _users) { if (userName == user->name()) { return true; } } return false; } void Room::_handleDice() { if (((_type & rounds) == rounds)) { if (_roundRunning && (_users.size() < 2 || _roundStart + _roundLength >= time(NULL))) { _lastRoundEnd = time(NULL); _roundRunning = false; addMessage(User::system, "round_ends"); _showDiceRoundResults(); } else if (!_roundRunning && _lastRoundEnd <= time(NULL) - 15 && _users.size() >= 2) { _roundStart = time(NULL); _roundRunning = true; _diceValues.clear(); addMessage(User::system, "next_round_starts_now"); } } } void Room::_initRound() { if (_users.size() == 2) { _lastRoundEnd = time(NULL); addMessage(User::system, "next_round_starts_soon"); } } void Room::_showDiceRoundResults() { std::sort(_diceValues.begin(), _diceValues.end(), [=](const std::pair, int>& val1, const std::pair, int>& val2) { return (val1.second > val2.second); }); Json::Value userList = Json::arrayValue; for (auto &user: _diceValues) { Json::Value entry = Json::objectValue; entry["name"] = user.first->name(); entry["value"] = user.second; userList.append(entry); } addMessage(User::result, userList); } std::string Room::name() { return _name; } } // namespace Lib } // namespace Yc