More smart pointers, clean up threading a little
The threading is still not good
This commit is contained in:
parent
079dab7c91
commit
3f8e6bf5f5
@ -49,7 +49,7 @@ ClientConnection::ClientConnection() {
|
|||||||
websocketpp::lib::placeholders::_1
|
websocketpp::lib::placeholders::_1
|
||||||
));
|
));
|
||||||
|
|
||||||
gHandler = new GatewayHandler();
|
gh = std::make_unique<GatewayHandler>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Open a connection to the URI provided
|
// Open a connection to the URI provided
|
||||||
@ -111,8 +111,9 @@ void ClientConnection::on_message(websocketpp::connection_hdl hdl, message_ptr m
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Pass the message to the gateway handler
|
// Pass the message to the gateway handler
|
||||||
gHandler->handle_data(message->get_payload(), c, hdl);
|
gh->handle_data(message->get_payload(), c, hdl);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientConnection::on_close(websocketpp::connection_hdl) {
|
void ClientConnection::on_close(websocketpp::connection_hdl) {
|
||||||
|
@ -14,7 +14,7 @@ typedef websocketpp::config::asio_tls_client::message_type::ptr message_ptr;
|
|||||||
typedef websocketpp::lib::shared_ptr<boost::asio::ssl::context> context_ptr;
|
typedef websocketpp::lib::shared_ptr<boost::asio::ssl::context> context_ptr;
|
||||||
typedef client::connection_ptr connection_ptr;
|
typedef client::connection_ptr connection_ptr;
|
||||||
|
|
||||||
class GatewayHandler;
|
#include "GatewayHandler.hpp"
|
||||||
|
|
||||||
class ClientConnection {
|
class ClientConnection {
|
||||||
public:
|
public:
|
||||||
@ -33,7 +33,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
client c;
|
client c;
|
||||||
GatewayHandler *gHandler;
|
std::unique_ptr<GatewayHandler> gh;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -31,23 +31,19 @@ void GatewayHandler::handle_data(std::string data, client &c, websocketpp::conne
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GatewayHandler::heartbeat(websocketpp::lib::error_code const & ec, client *c, websocketpp::connection_hdl *hdl) {
|
void GatewayHandler::heartbeat(client *c, websocketpp::connection_hdl hdl, int interval) {
|
||||||
json heartbeat = {
|
while (true) {
|
||||||
{ "op", 1 },
|
boost::this_thread::sleep(boost::posix_time::milliseconds(interval));
|
||||||
{ "d", last_seq }
|
|
||||||
};
|
|
||||||
|
|
||||||
c->send(*hdl, heartbeat.dump(), websocketpp::frame::opcode::text);
|
json heartbeat = {
|
||||||
|
{ "op", 1 },
|
||||||
|
{ "d", last_seq }
|
||||||
|
};
|
||||||
|
|
||||||
c->set_timer(heartbeat_interval, websocketpp::lib::bind(
|
c->send(hdl, heartbeat.dump(), websocketpp::frame::opcode::text);
|
||||||
&GatewayHandler::heartbeat,
|
|
||||||
this,
|
|
||||||
websocketpp::lib::placeholders::_1,
|
|
||||||
c,
|
|
||||||
hdl
|
|
||||||
));
|
|
||||||
|
|
||||||
c->get_alog().write(websocketpp::log::alevel::app, "Sent heartbeat. (seq: " + std::to_string(last_seq) + ")");
|
c->get_alog().write(websocketpp::log::alevel::app, "Sent heartbeat. (seq: " + std::to_string(last_seq) + ")");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GatewayHandler::on_hello(json decoded, client &c, websocketpp::connection_hdl &hdl) {
|
void GatewayHandler::on_hello(json decoded, client &c, websocketpp::connection_hdl &hdl) {
|
||||||
@ -55,13 +51,7 @@ void GatewayHandler::on_hello(json decoded, client &c, websocketpp::connection_h
|
|||||||
|
|
||||||
c.get_alog().write(websocketpp::log::alevel::app, "Heartbeat interval: " + std::to_string(heartbeat_interval / 1000.0f) + " seconds");
|
c.get_alog().write(websocketpp::log::alevel::app, "Heartbeat interval: " + std::to_string(heartbeat_interval / 1000.0f) + " seconds");
|
||||||
|
|
||||||
c.set_timer(heartbeat_interval, websocketpp::lib::bind(
|
heartbeat_thread = std::make_unique<boost::thread>(boost::bind(&GatewayHandler::heartbeat, this, &c, hdl, heartbeat_interval));
|
||||||
&GatewayHandler::heartbeat,
|
|
||||||
this,
|
|
||||||
websocketpp::lib::placeholders::_1,
|
|
||||||
&c,
|
|
||||||
&hdl
|
|
||||||
));
|
|
||||||
|
|
||||||
identify(c, hdl);
|
identify(c, hdl);
|
||||||
}
|
}
|
||||||
@ -78,13 +68,22 @@ void GatewayHandler::on_dispatch(json decoded, client &c, websocketpp::connectio
|
|||||||
}
|
}
|
||||||
else if (event_name == "GUILD_CREATE") {
|
else if (event_name == "GUILD_CREATE") {
|
||||||
std::string guild_id = data["id"];
|
std::string guild_id = data["id"];
|
||||||
guilds[guild_id] = std::make_unique<DiscordObjects::Guild>(data);
|
try {
|
||||||
|
guilds[guild_id] = std::make_unique<DiscordObjects::Guild>(data);
|
||||||
|
}
|
||||||
|
catch (std::domain_error err) {
|
||||||
|
// this doesn't even work
|
||||||
|
c.get_alog().write(websocketpp::log::elevel::rerror, "Domain error");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
c.get_alog().write(websocketpp::log::alevel::app, "Loaded guild: " + guilds[guild_id]->name);
|
||||||
|
|
||||||
for (json channel : data["channels"]) {
|
for (json channel : data["channels"]) {
|
||||||
std::string channel_id = channel["id"];
|
std::string channel_id = channel["id"];
|
||||||
channel["guild_id"] = guild_id;
|
channel["guild_id"] = guild_id;
|
||||||
// create channel obj, add to overall channel list
|
// create channel obj, add to overall channel list
|
||||||
channels[channel_id] = std::make_unique<DiscordObjects::Channel>(channel);
|
channels[channel_id] = std::make_shared<DiscordObjects::Channel>(channel);
|
||||||
// add ptr to said channel list to guild's channel list
|
// add ptr to said channel list to guild's channel list
|
||||||
guilds[guild_id]->channels.push_back(std::shared_ptr<DiscordObjects::Channel>(channels[channel_id]));
|
guilds[guild_id]->channels.push_back(std::shared_ptr<DiscordObjects::Channel>(channels[channel_id]));
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,7 @@ public:
|
|||||||
|
|
||||||
void handle_data(std::string data, client &c, websocketpp::connection_hdl &hdl);
|
void handle_data(std::string data, client &c, websocketpp::connection_hdl &hdl);
|
||||||
|
|
||||||
void heartbeat(websocketpp::lib::error_code const & ec, client *c, websocketpp::connection_hdl *hdl);
|
void heartbeat(client *c, websocketpp::connection_hdl hdl, int interval);
|
||||||
|
|
||||||
void on_hello(json decoded, client &c, websocketpp::connection_hdl &hdl);
|
void on_hello(json decoded, client &c, websocketpp::connection_hdl &hdl);
|
||||||
|
|
||||||
@ -69,6 +69,8 @@ private:
|
|||||||
// <channel_id, game obj>
|
// <channel_id, game obj>
|
||||||
std::map<std::string, std::unique_ptr<TriviaGame>> games;
|
std::map<std::string, std::unique_ptr<TriviaGame>> games;
|
||||||
|
|
||||||
|
std::unique_ptr<boost::thread> heartbeat_thread;
|
||||||
|
|
||||||
APIHelper *ah;
|
APIHelper *ah;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -23,6 +23,8 @@ TriviaGame::TriviaGame(GatewayHandler *gh, APIHelper *ah, std::string channel_id
|
|||||||
}
|
}
|
||||||
|
|
||||||
TriviaGame::~TriviaGame() {
|
TriviaGame::~TriviaGame() {
|
||||||
|
current_thread.reset();
|
||||||
|
|
||||||
if (scores.size() == 0) {
|
if (scores.size() == 0) {
|
||||||
ah->send_message(channel_id, ":red_circle: Game cancelled!");
|
ah->send_message(channel_id, ":red_circle: Game cancelled!");
|
||||||
return;
|
return;
|
||||||
@ -164,7 +166,7 @@ TriviaGame::~TriviaGame() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TriviaGame::start() {
|
void TriviaGame::start() {
|
||||||
question();
|
current_thread = std::make_unique<boost::thread>(boost::bind(&TriviaGame::question, this));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TriviaGame::interrupt() {
|
void TriviaGame::interrupt() {
|
||||||
@ -172,127 +174,118 @@ void TriviaGame::interrupt() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TriviaGame::question() {
|
void TriviaGame::question() {
|
||||||
sqlite3 *db; int rc; std::string sql;
|
while (questions_asked < total_questions) {
|
||||||
|
sqlite3 *db; int rc; std::string sql;
|
||||||
|
|
||||||
/// open db
|
/// open db
|
||||||
rc = sqlite3_open("bot/db/trivia.db", &db);
|
rc = sqlite3_open("bot/db/trivia.db", &db);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
std::cerr << "Cant't open database: " << sqlite3_errmsg(db) << std::endl;
|
std::cerr << "Cant't open database: " << sqlite3_errmsg(db) << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
// prepare statement
|
// prepare statement
|
||||||
sqlite3_stmt *stmt;
|
sqlite3_stmt *stmt;
|
||||||
sql = "SELECT * FROM Questions ORDER BY RANDOM() LIMIT 1;";
|
sql = "SELECT * FROM Questions ORDER BY RANDOM() LIMIT 1;";
|
||||||
rc = sqlite3_prepare_v2(db, sql.c_str(), -1, &stmt, 0);
|
rc = sqlite3_prepare_v2(db, sql.c_str(), -1, &stmt, 0);
|
||||||
|
|
||||||
if (rc != SQLITE_OK) {
|
if (rc != SQLITE_OK) {
|
||||||
std::cerr << "SQL error." << std::endl;
|
std::cerr << "SQL error." << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = sqlite3_step(stmt);
|
rc = sqlite3_step(stmt);
|
||||||
if (rc == SQLITE_ROW) {
|
if (rc == SQLITE_ROW) {
|
||||||
// result received
|
// result received
|
||||||
std::string id = reinterpret_cast<const char *>(sqlite3_column_text(stmt, 0)); // converts id to string for us
|
std::string id = reinterpret_cast<const char *>(sqlite3_column_text(stmt, 0)); // converts id to string for us
|
||||||
std::string category = reinterpret_cast<const char *>(sqlite3_column_text(stmt, 1));
|
std::string category = reinterpret_cast<const char *>(sqlite3_column_text(stmt, 1));
|
||||||
std::string question = reinterpret_cast<const char *>(sqlite3_column_text(stmt, 2));
|
std::string question = reinterpret_cast<const char *>(sqlite3_column_text(stmt, 2));
|
||||||
std::string answer = reinterpret_cast<const char *>(sqlite3_column_text(stmt, 3));
|
std::string answer = reinterpret_cast<const char *>(sqlite3_column_text(stmt, 3));
|
||||||
|
|
||||||
|
current_question = "#" + id + " [" + category + "] **" + question + "**";
|
||||||
|
boost::algorithm::to_lower(answer);
|
||||||
|
boost::split(current_answers, answer, boost::is_any_of("*"));
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (rc != SQLITE_DONE) {
|
||||||
|
sqlite3_finalize(stmt);
|
||||||
|
std::cerr << "SQLite error." << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
current_question = "#" + id + " [" + category + "] **" + question + "**";
|
|
||||||
boost::algorithm::to_lower(answer);
|
|
||||||
boost::split(current_answers, answer, boost::is_any_of("*"));
|
|
||||||
|
|
||||||
} else if (rc != SQLITE_DONE) {
|
|
||||||
sqlite3_finalize(stmt);
|
sqlite3_finalize(stmt);
|
||||||
std::cerr << "SQLite error." << std::endl;
|
sqlite3_close(db);
|
||||||
|
|
||||||
|
questions_asked++;
|
||||||
|
ah->send_message(channel_id, ":question: **(" + std::to_string(questions_asked) + "/" + std::to_string(total_questions) + ")** " + current_question);
|
||||||
|
question_start = boost::posix_time::microsec_clock::universal_time();
|
||||||
|
|
||||||
|
give_hint(0, "");
|
||||||
}
|
}
|
||||||
|
gh->delete_game(channel_id);
|
||||||
sqlite3_finalize(stmt);
|
|
||||||
sqlite3_close(db);
|
|
||||||
|
|
||||||
questions_asked++;
|
|
||||||
ah->send_message(channel_id, ":question: **(" + std::to_string(questions_asked) + "/" + std::to_string(total_questions) + ")** " + current_question);
|
|
||||||
question_start = boost::posix_time::microsec_clock::universal_time();
|
|
||||||
|
|
||||||
current_thread = std::make_unique<boost::thread>(boost::bind(&TriviaGame::give_hint, this, 0, ""));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TriviaGame::give_hint(int hints_given, std::string hint) {
|
void TriviaGame::give_hint(int hints_given, std::string hint) {
|
||||||
boost::this_thread::sleep(interval);
|
while (hints_given < 4) {
|
||||||
|
boost::this_thread::sleep(interval);
|
||||||
|
|
||||||
std::string answer = *current_answers.begin();
|
std::string answer = *current_answers.begin();
|
||||||
|
|
||||||
bool print = false;
|
bool print = false;
|
||||||
|
|
||||||
if (hints_given == 0) {
|
if (hints_given == 0) {
|
||||||
hint = answer;
|
hint = answer;
|
||||||
// probably shouldn't use regex here
|
// probably shouldn't use regex here
|
||||||
boost::regex regexp("[a-zA-Z0-9]+?");
|
boost::regex regexp("[a-zA-Z0-9]+?");
|
||||||
hint = boost::regex_replace(hint, regexp, std::string(1, hide_char));
|
hint = boost::regex_replace(hint, regexp, std::string(1, hide_char));
|
||||||
|
|
||||||
print = true;
|
print = true;
|
||||||
} else {
|
} else {
|
||||||
std::stringstream hint_stream(hint);
|
std::stringstream hint_stream(hint);
|
||||||
|
|
||||||
std::random_device rd;
|
std::random_device rd;
|
||||||
std::mt19937 rng(rd());
|
std::mt19937 rng(rd());
|
||||||
|
|
||||||
std::vector<std::string> hint_words, answer_words;
|
std::vector<std::string> hint_words, answer_words;
|
||||||
boost::split(hint_words, hint, boost::is_any_of(" "));
|
boost::split(hint_words, hint, boost::is_any_of(" "));
|
||||||
boost::split(answer_words, answer, boost::is_any_of(" "));
|
boost::split(answer_words, answer, boost::is_any_of(" "));
|
||||||
|
|
||||||
hint = "";
|
hint = "";
|
||||||
for (unsigned int i = 0; i < hint_words.size(); i++) {
|
for (unsigned int i = 0; i < hint_words.size(); i++) {
|
||||||
std::string word = hint_words[i];
|
std::string word = hint_words[i];
|
||||||
|
|
||||||
// count number of *s
|
// count number of *s
|
||||||
int length = 0;
|
int length = 0;
|
||||||
for (unsigned int i = 0; i < word.length(); i++) {
|
for (unsigned int i = 0; i < word.length(); i++) {
|
||||||
if (word[i] == hide_char) {
|
if (word[i] == hide_char) {
|
||||||
length++;
|
length++;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (length > 1) {
|
|
||||||
std::uniform_int_distribution<int> uni(0, word.length() - 1);
|
|
||||||
|
|
||||||
bool replaced = false;
|
|
||||||
while (!replaced) {
|
|
||||||
int replace_index = uni(rng);
|
|
||||||
if (word[replace_index] == hide_char) {
|
|
||||||
word[replace_index] = answer_words[i][replace_index];
|
|
||||||
|
|
||||||
print = true;
|
|
||||||
replaced = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
hint += word + " ";
|
if (length > 1) {
|
||||||
|
std::uniform_int_distribution<int> uni(0, word.length() - 1);
|
||||||
|
|
||||||
|
bool replaced = false;
|
||||||
|
while (!replaced) {
|
||||||
|
int replace_index = uni(rng);
|
||||||
|
if (word[replace_index] == hide_char) {
|
||||||
|
word[replace_index] = answer_words[i][replace_index];
|
||||||
|
|
||||||
|
print = true;
|
||||||
|
replaced = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
hint += word + " ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
hints_given++; // now equal to the amount of [hide_char]s that need to be present in each word
|
||||||
|
|
||||||
|
if (print) {
|
||||||
|
ah->send_message(channel_id, ":small_orange_diamond: Hint: **`" + hint + "`**");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
hints_given++; // now equal to the amount of [hide_char]s that need to be present in each word
|
|
||||||
|
|
||||||
if (print) {
|
|
||||||
ah->send_message(channel_id, ":small_orange_diamond: Hint: **`" + hint + "`**");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hints_given < 4) {
|
|
||||||
current_thread = std::make_unique<boost::thread>(boost::bind(&TriviaGame::give_hint, this, hints_given, hint));
|
|
||||||
} else {
|
|
||||||
current_thread = std::make_unique<boost::thread>(boost::bind(&TriviaGame::question_failed, this));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TriviaGame::question_failed() {
|
|
||||||
boost::this_thread::sleep(interval);
|
boost::this_thread::sleep(interval);
|
||||||
ah->send_message(channel_id, ":exclamation: Question failed. Answer: ** `" + *current_answers.begin() + "` **");
|
ah->send_message(channel_id, ":exclamation: Question failed. Answer: ** `" + *current_answers.begin() + "` **");
|
||||||
|
|
||||||
if (questions_asked < total_questions) {
|
|
||||||
question();
|
|
||||||
} else {
|
|
||||||
gh->delete_game(channel_id);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TriviaGame::handle_answer(std::string answer, DiscordObjects::User sender) {
|
void TriviaGame::handle_answer(std::string answer, DiscordObjects::User sender) {
|
||||||
@ -312,7 +305,8 @@ void TriviaGame::handle_answer(std::string answer, DiscordObjects::User sender)
|
|||||||
update_average_time(sender.id, diff.total_milliseconds());
|
update_average_time(sender.id, diff.total_milliseconds());
|
||||||
|
|
||||||
if (questions_asked < total_questions) {
|
if (questions_asked < total_questions) {
|
||||||
question();
|
interrupt(); current_thread.reset(); // don't know if required
|
||||||
|
current_thread = std::make_unique<boost::thread>(boost::bind(&TriviaGame::question, this));
|
||||||
} else {
|
} else {
|
||||||
gh->delete_game(channel_id);
|
gh->delete_game(channel_id);
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,6 @@ private:
|
|||||||
|
|
||||||
void question();
|
void question();
|
||||||
void give_hint(int hints_given, std::string hint);
|
void give_hint(int hints_given, std::string hint);
|
||||||
void question_failed();
|
|
||||||
void increase_score(std::string user_id);
|
void increase_score(std::string user_id);
|
||||||
void update_average_time(std::string user_id, int time);
|
void update_average_time(std::string user_id, int time);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user