Cavoke  1.1.0
A Platform for creating and hosting multiplayer turn-based board games
Loading...
Searching...
No Matches
state_controller.cpp
1#include "state_controller.h"
2#include <utility>
3
4namespace cavoke::server::controllers {
5
6using json = nlohmann::json;
7
8void StateController::send_move(
9 const drogon::HttpRequestPtr &req,
10 std::function<void(const drogon::HttpResponsePtr &)> &&callback,
11 const std::string &session_id) {
12 // get user id
13 auto user_id = AuthFilter::get_user_id(req);
14
15 {
16 auto transaction = drogon::app().getDbClient()->newTransaction();
17 model::GameSessionAccessObject session_with_transaction;
18 try {
19 session_with_transaction =
20 m_participation_storage->get_sessionAO(session_id, transaction);
21 } catch (const model::game_session_error &) {
22 transaction->rollback();
23 return CALLBACK_STATUS_CODE(k400BadRequest);
24 }
25
26 int player_id;
27 try {
28 player_id = session_with_transaction.get_player_id(user_id);
29 } catch (const model::game_session_error &) {
30 transaction->rollback();
31 return CALLBACK_STATUS_CODE(k403Forbidden);
32 }
33
34 auto session_info = session_with_transaction.get_session_info();
35
36 if (session_info.status == model::GameSessionAccessObject::FINISHED) {
37 transaction->rollback();
38 return CALLBACK_STATUS_CODE(k403Forbidden);
39 }
40 if (session_info.status ==
41 model::GameSessionAccessObject::NOT_STARTED) {
42 transaction->rollback();
43 return CALLBACK_STATUS_CODE(k404NotFound);
44 }
45
46 json json_body;
47 try {
48 json_body = json::parse(req->getBody());
49 } catch (const json::parse_error &) {
50 transaction->rollback();
51 return CALLBACK_STATUS_CODE(k400BadRequest);
52 }
53 if (!json_body.contains("move") || !json_body["move"].is_string()) {
54 transaction->rollback();
55 return CALLBACK_STATUS_CODE(k400BadRequest);
56 }
57
58 std::string move = json_body["move"];
59
60 model::GameStateStorage::GameState current_state;
61 try {
62 current_state =
63 m_game_state_storage->get_state(session_id, transaction);
64 } catch (const model::game_state_error &) {
65 transaction->rollback();
66 return CALLBACK_STATUS_CODE(k404NotFound);
67 }
68
69 auto next_state = m_game_logic_manager->send_move(
70 session_info.game_id,
71 {player_id, move, current_state.global_state});
72
73 m_game_state_storage->save_state(session_id, next_state, transaction);
74
75 session_with_transaction.update_status(next_state.is_terminal);
76 if (next_state.is_terminal) {
77 LOG_INFO << "Session " << session_id
78 << " is being declared finished!";
79 }
80
81 transaction->setCommitCallback([next_state, player_id](bool committed) {
82 LOG_TRACE << "State set (" << committed << ") state: '"
83 << next_state.global_state << "' player_id=" << player_id;
84 });
85 }
86
87 auto resp = drogon::HttpResponse::newHttpResponse();
88 resp->setStatusCode(drogon::HttpStatusCode::k200OK);
89 callback(resp);
90}
91
92void StateController::get_state(
93 const drogon::HttpRequestPtr &req,
94 std::function<void(const drogon::HttpResponsePtr &)> &&callback,
95 const std::string &session_id) {
96 // get user id
97 auto user_id = AuthFilter::get_user_id(req);
98
99 auto transaction = drogon::app().getDbClient()->newTransaction();
100 model::GameSessionAccessObject session_with_transaction;
101 try {
102 session_with_transaction =
103 m_participation_storage->get_sessionAO(session_id, transaction);
104 } catch (const model::game_session_error &) {
105 transaction->rollback();
106 return CALLBACK_STATUS_CODE(k404NotFound);
107 }
108
109 int player_id;
110 try {
111 player_id = session_with_transaction.get_player_id(user_id);
112 } catch (const model::game_session_error &) {
113 transaction->rollback();
114 return CALLBACK_STATUS_CODE(k403Forbidden);
115 }
116
117 auto session_info = session_with_transaction.get_session_info();
118
119 if (session_info.status == model::GameSessionAccessObject::NOT_STARTED) {
120 transaction->rollback();
121 return CALLBACK_STATUS_CODE(k404NotFound);
122 }
123
124 std::string player_state;
125 try {
126 player_state = m_game_state_storage->get_player_state(
127 session_id, player_id, transaction);
128 } catch (const model::game_state_error &) {
129 }
130
131 json resp_json;
132 resp_json["state"] = std::move(player_state);
133 auto game_state = m_game_state_storage->get_state(session_id, transaction);
134 resp_json["is_terminal"] = game_state.is_terminal;
135 if (game_state.is_terminal) {
136 std::vector<std::string> winners;
137 for (const auto &e : game_state.winners) {
138 // cppcheck-suppress useStlAlgorithm
139 winners.push_back(session_with_transaction.get_user_id(e));
140 }
141 resp_json["winners"] = winners;
142 }
143
144 transaction->setCommitCallback(
145 [player_state = resp_json["state"].get<std::string>(),
146 player_id](bool committed) {
147 LOG_TRACE << "Got state (" << committed << ") state: '"
148 << player_state << "' player_id=" << player_id;
149 });
150
151 auto resp = newNlohmannJsonResponse(resp_json);
152 callback(resp);
153}
154
155StateController::StateController(
156 std::shared_ptr<model::GamesStorage> mGamesStorage,
157 std::shared_ptr<model::GameLogicManager> mGameLogicManager,
158 std::shared_ptr<model::GameStateStorage> mGameStateStorage,
159 std::shared_ptr<model::SessionsStorage> mParticipationStorage)
160 : m_games_storage(std::move(mGamesStorage)),
161 m_game_logic_manager(std::move(mGameLogicManager)),
162 m_game_state_storage(std::move(mGameStateStorage)),
163 m_participation_storage(std::move(mParticipationStorage)) {
164}
165
166} // namespace cavoke::server::controllers
static std::string get_user_id(const HttpRequestPtr &)
Acquires user_id parsed during AuthFilter's execution.
Definition: AuthFilter.cc:82