#include "room.h" #include #include #include #include #include #include #include #include namespace Yc { namespace Lib { Room::Room(Server *parent, Json::Value roomParams) : _parent(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 = new std::thread(&Room::run, this); } Room::~Room() { delete thread; } 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; } User *newUser = new User(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(User *user, std::string password) { if (password == _password) { _users.push_back(user); user->setParent(this); _initRound(); return true; } return false; } bool Room::userNameExists(std::string userName) { for (auto &user: _users) { if (user->name() == userName) { return true; } } return false; } void Room::removeUser(std::string _token, bool silent) { for (std::vector::iterator user = _users.begin(); user != _users.end(); ++user) { if ((*user)->validateToken(_token)) { _users.erase(user); if (!silent) { addMessage(User::system, "room_exit", (*user)->name(), (*user)->color()); } break; } } } void Room::removeUser(User *userToRemove, bool silent) { for (std::vector::iterator user = _users.begin(); user != _users.end(); ++user) { if (*user == userToRemove) { _users.erase(user); if (!silent) { addMessage(User::system, "room_exit", (*user)->name(), (*user)->color()); } 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(User *user) { while (_msgQueue.size() > 0) { std::this_thread::sleep_for(std::chrono::milliseconds(100)); } _users.push_back(user); user->setParent(this); } bool Room::userToNewRoom(User *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; } 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(User *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(), [=](std::pair val1, std::pair val2) { return (val1.second > val2.second); }); Json::Value userList = Json::arrayValue; for (auto &user: _diceValues) { Json::Value entry = Json::objectValue; entry["name"] = user.first; entry["value"] = user.second; userList.append(entry); } addMessage(User::result, userList); } std::string Room::name() { return _name; } } // namespace Lib } // namespace Yc