1#include "rooms_storage.h"
3#include "drogon/orm/Criteria.h"
4#include "sql-models/RoomJoins.h"
6namespace cavoke::server::model {
8using namespace drogon::orm;
10RoomsStorage::RoomsStorage(std::shared_ptr<SessionsStorage> mSessionsStorage)
11 : m_sessions_storage(std::move(mSessionsStorage)) {
14std::optional<RoomsStorage::RoomInfo> RoomsStorage::get_by_id(
15 const std::string &room_id) {
16 auto mp_rooms_trans = MAPPER_FOR(drogon_model::cavoke_orm::Rooms);
18 const auto &room = mp_rooms_trans.findByPrimaryKey(room_id);
19 const auto &members = get_members(room_id);
20 return RoomInfo::from_room_and_members(room, members);
21 }
catch (
const UnexpectedRows &e) {
26std::vector<GameSessionAccessObject::UserInfo> RoomsStorage::get_members(
27 const std::string &room_id) {
28 auto mp_rooms_trans = MAPPER_FOR(drogon_model::cavoke_orm::Rooms);
29 auto mp_joins_trans = MAPPER_FOR(drogon_model::cavoke_orm::RoomJoins);
30 auto mp_users_trans = MAPPER_FOR(
31 drogon_model::cavoke_orm::Users);
33 auto joins = mp_joins_trans.findBy(
34 Criteria(drogon_model::cavoke_orm::RoomJoins::Cols::_room_id,
35 CompareOperator::EQ, room_id));
37 std::vector<GameSessionAccessObject::UserInfo> members;
38 members.reserve(joins.size());
40 joins.begin(), joins.end(), std::back_inserter(members),
41 [&mp_users_trans](
const drogon_model::cavoke_orm::RoomJoins &join) {
42 return GameSessionAccessObject::UserInfo::from_user(
43 mp_users_trans.findByPrimaryKey(join.getValueOfUserId()));
49std::optional<RoomsStorage::RoomInfo> RoomsStorage::get_by_invite_code(
50 const std::string &invite_code) {
51 auto transaction = drogon::app().getDbClient()->newTransaction();
52 auto mp_rooms_trans = MAPPER_FOR(drogon_model::cavoke_orm::Rooms);
54 const auto &room = mp_rooms_trans.findOne(
55 Criteria(drogon_model::cavoke_orm::Rooms::Cols::_invite_code,
56 CompareOperator::EQ, invite_code));
57 const auto &members = get_members(room.getValueOfId());
58 return RoomInfo::from_room_and_members(room, members);
60 }
catch (
const UnexpectedRows &) {
65void RoomsStorage::add_user(
const std::string &room_id,
66 const std::string &user_id) {
67 if (is_member(room_id, user_id)) {
71 if (!get_by_id(room_id).has_value()) {
72 throw room_error(
"Cannot add user. No room with id " + room_id);
75 auto join = drogon_model::cavoke_orm::RoomJoins();
77 join.setRoomId(room_id);
78 join.setUserId(user_id);
81 auto mp_joins_trans = MAPPER_FOR(drogon_model::cavoke_orm::RoomJoins);
82 mp_joins_trans.insert(join);
85void RoomsStorage::remove_user(
const std::string &room_id,
86 const std::string &user_id) {
87 if (!is_member(room_id, user_id)) {
90 drogon::app().getDbClient()->execSqlSync(
91 "select leave_room($1::uuid, $2::varchar);", room_id, user_id);
94bool RoomsStorage::is_member(
const std::string &room_id,
95 const std::string &user_id) {
96 auto mp_joins_trans = MAPPER_FOR(drogon_model::cavoke_orm::RoomJoins);
97 size_t joins_count = mp_joins_trans.count(
98 Criteria(drogon_model::cavoke_orm::RoomJoins::Cols::_room_id,
99 CompareOperator::EQ, room_id) &&
100 Criteria(drogon_model::cavoke_orm::RoomJoins::Cols::_user_id,
101 CompareOperator::EQ, user_id));
102 return joins_count > 0;
105RoomsStorage::RoomInfo RoomsStorage::create_room(
106 const std::string &host_id,
107 const std::string &display_name) {
108 auto room = drogon_model::cavoke_orm::Rooms();
110 room.setId(drogon::utils::getUuid());
111 room.setDisplayName(display_name);
112 room.setSessionIdToNull();
115 auto join = drogon_model::cavoke_orm::RoomJoins();
117 join.setRoomId(room.getValueOfId());
118 join.setUserId(host_id);
124 auto mp_rooms_trans = MAPPER_FOR(drogon_model::cavoke_orm::Rooms);
125 auto mp_joins_trans = MAPPER_FOR(drogon_model::cavoke_orm::RoomJoins);
127 mp_rooms_trans.insert(room);
128 mp_joins_trans.insert(join);
130 room = mp_rooms_trans.findByPrimaryKey(room.getValueOfId());
131 room.setHostId(host_id);
132 mp_rooms_trans.update(room);
135 return RoomsStorage::RoomInfo::from_room_and_members(
136 room, get_members(room.getValueOfId()));
139GameSessionAccessObject::GameSessionInfo RoomsStorage::create_session(
140 const std::string &room_id,
141 const GameConfig &game_config) {
142 auto opt_room_info = get_by_id(room_id);
143 if (!opt_room_info.has_value()) {
144 throw room_error(
"Cannot create session. No room with id " + room_id);
146 auto room_info = opt_room_info.value();
148 if (!room_info.session_id.empty()) {
149 auto current_session =
150 m_sessions_storage->get_sessionAO(room_info.session_id);
151 if (current_session.get_session_info().status !=
152 GameSessionAccessObject::SessionStatus::FINISHED) {
153 throw room_error(
"Cannot create session in room " + room_id +
154 ". Session already exists and not "
159 auto new_session = m_sessions_storage->create_session(
160 game_config, room_info.host_id, room_id);
165room_error::room_error(std::string message)
166 : cavoke_base_exception(std::move(message),
171RoomsStorage::RoomInfo RoomsStorage::RoomInfo::from_room_and_members(
172 const drogon_model::cavoke_orm::Rooms &room_orm,
173 const std::vector<GameSessionAccessObject::UserInfo> &members) {
174 return {room_orm.getValueOfId(),
175 room_orm.getValueOfInviteCode(),
176 room_orm.getValueOfDisplayName(),
177 room_orm.getValueOfSessionId(),
179 room_orm.getValueOfHostId(),