summary refs log tree commit diff stats
path: root/lingo.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lingo.cpp')
-rw-r--r--lingo.cpp548
1 files changed, 298 insertions, 250 deletions
diff --git a/lingo.cpp b/lingo.cpp index b417ffb..3b60c82 100644 --- a/lingo.cpp +++ b/lingo.cpp
@@ -2,6 +2,7 @@
2#include <random> 2#include <random>
3#include <yaml-cpp/yaml.h> 3#include <yaml-cpp/yaml.h>
4#include <iostream> 4#include <iostream>
5#include <memory>
5#include <thread> 6#include <thread>
6#include <mutex> 7#include <mutex>
7#include <chrono> 8#include <chrono>
@@ -41,231 +42,132 @@ const std::string COLOUR_EMOJIS[kColourCount] = {
41 "🟨" 42 "🟨"
42}; 43};
43 44
44int main(int argc, char** argv) 45class lingo {
45{ 46public:
46 std::random_device randomDevice; 47 lingo(std::mt19937& rng) : rng_(rng) {}
47 std::mt19937 rng{randomDevice()};
48 48
49 if (argc != 2) 49 void run(const std::string& configpath)
50 { 50 {
51 std::cout << "usage: lingo [configfile]" << std::endl; 51 YAML::Node config = YAML::LoadFile(configpath);
52 return -1; 52 bot_ = std::make_unique<dpp::cluster>(config["discord_token"].as<std::string>());
53 }
54 53
55 std::string configfile(argv[1]); 54 bot_->on_ready([this](const dpp::ready_t& event) {
56 YAML::Node config = YAML::LoadFile(configfile); 55 if (dpp::run_once<struct register_bot_commands>())
56 {
57 dpp::slashcommand newcommand("newpuzzle", "Generate a new LINGO puzzle", bot_->me.id);
58 bot_->global_command_create(newcommand);
59 }
60 });
57 61
58 std::map<uint64_t, std::string> answer_by_message; 62 bot_->on_slashcommand([this](const dpp::slashcommand_t& event) {
59 std::mutex answers_mutex; 63 if (event.command.get_command_name() == "newpuzzle") {
64 event.thinking(true);
60 65
61 dpp::cluster bot(config["discord_token"].as<std::string>()); 66 std::thread genpuzz(&lingo::generatePuzzle, this, event.command.get_channel().id);
62 bot.on_message_create([&bot, &answers_mutex, &answer_by_message](const dpp::message_create_t& event) { 67 genpuzz.detach();
63 std::lock_guard answer_lock(answers_mutex);
64 if (answer_by_message.count(event.msg.message_reference.message_id))
65 {
66 std::string canonical_answer = hatkirby::lowercase(answer_by_message[event.msg.message_reference.message_id]);
67 std::string canonical_attempt = hatkirby::lowercase(event.msg.content);
68 while (canonical_attempt.find("||") != std::string::npos)
69 {
70 canonical_attempt.erase(canonical_attempt.find("||"), 2);
71 } 68 }
69 });
72 70
73 if (canonical_attempt == canonical_answer) 71 bot_->on_message_create([this](const dpp::message_create_t& event) {
72 std::lock_guard answer_lock(answers_mutex_);
73 if (answer_by_message_.count(event.msg.message_reference.message_id))
74 { 74 {
75 bot.message_add_reaction(event.msg.id, event.msg.channel_id, "✅"); 75 std::string canonical_answer = hatkirby::lowercase(answer_by_message_[event.msg.message_reference.message_id]);
76 } else { 76 std::string canonical_attempt = hatkirby::lowercase(event.msg.content);
77 bot.message_add_reaction(event.msg.id, event.msg.channel_id, "❌"); 77 while (canonical_attempt.find("||") != std::string::npos)
78 {
79 canonical_attempt.erase(canonical_attempt.find("||"), 2);
80 }
81
82 if (canonical_attempt == canonical_answer)
83 {
84 bot_->message_add_reaction(event.msg.id, event.msg.channel_id, "✅");
85 } else {
86 bot_->message_add_reaction(event.msg.id, event.msg.channel_id, "❌");
87 }
78 } 88 }
89 });
90
91 bot_->start();
92
93 dpp::snowflake channel(config["discord_channel"].as<uint64_t>());
94
95 database_ = std::make_unique<verbly::database>(config["verbly_datafile"].as<std::string>());
96
97 for (;;)
98 {
99 std::thread genpuzz(&lingo::generatePuzzle, this, channel);
100 genpuzz.detach();
101
102 std::this_thread::sleep_for(std::chrono::hours(24));
79 } 103 }
80 }); 104 }
81 bot.start(); 105
82 106private:
83 dpp::snowflake channel(config["discord_channel"].as<uint64_t>()); 107
84 108 void generatePuzzle(dpp::snowflake channel)
85 verbly::database database(config["verbly_datafile"].as<std::string>());
86
87 std::set<std::tuple<Height, Colour>> filters = {
88 {kTop, kPurple},
89 {kTop, kWhite},
90 {kTop, kYellow},
91 {kTop, kRed},
92 {kTop, kBlue},
93 {kMiddle, kYellow},
94 {kMiddle, kRed},
95 {kMiddle, kBlue},
96 {kMiddle, kPurple},
97 {kBottom, kWhite},
98 {kBottom, kBlack},
99 {kBottom, kRed},
100 {kBottom, kBlue},
101 };
102
103 verbly::filter wordFilter = (verbly::form::proper == false);
104
105 verbly::filter cleanFilter =
106 !(verbly::word::usageDomains %= (verbly::notion::wnid == 106718862)) // ethnic slurs
107 && !(verbly::notion::wnid == 110630093); // "spastic"
108
109 for (;;)
110 { 109 {
111 try 110 std::set<std::tuple<Height, Colour>> filters = {
112 { 111 {kTop, kPurple},
113 int hints = 0; 112 {kTop, kWhite},
114 std::array<std::optional<Colour>, kHeightCount> parts; 113 {kTop, kYellow},
115 for (int height = 0; height < static_cast<int>(kHeightCount); height++) { 114 {kTop, kRed},
116 if (std::bernoulli_distribution(0.5)(rng)) { 115 {kTop, kBlue},
117 int colour = std::uniform_int_distribution<int>(0, static_cast<int>(kColourCount)-1)(rng); 116 {kMiddle, kYellow},
118 if (filters.count({static_cast<Height>(height), static_cast<Colour>(colour)})) { 117 {kMiddle, kRed},
119 parts[static_cast<Height>(height)] = static_cast<Colour>(colour); 118 {kMiddle, kBlue},
120 hints++; 119 {kMiddle, kPurple},
121 } 120 {kBottom, kWhite},
122 } 121 {kBottom, kBlack},
123 } 122 {kBottom, kRed},
123 {kBottom, kBlue},
124 };
124 125
125 if (hints < 2) { 126 verbly::filter wordFilter = (verbly::form::proper == false);
126 continue;
127 }
128 127
129 verbly::filter forwardFilter = cleanFilter && (verbly::form::proper == false); 128 verbly::filter cleanFilter =
130 for (int i=0; i<static_cast<int>(kHeightCount); i++) { 129 !(verbly::word::usageDomains %= (verbly::notion::wnid == 106718862)) // ethnic slurs
131 Height height = static_cast<Height>(i); 130 && !(verbly::notion::wnid == 110630093); // "spastic"
132 std::optional<Colour>& colour = parts[i]; 131
133 if (!colour.has_value()) { 132 bool generated = false;
134 continue; 133 while (!generated)
135 } 134 {
136 switch (*colour) { 135 try
137 case kWhite: { 136 {
138 switch (height) { 137 int hints = 0;
139 case kBottom: { 138 std::array<std::optional<Colour>, kHeightCount> parts;
140 forwardFilter &= (verbly::word::synonyms %= wordFilter); 139 for (int height = 0; height < static_cast<int>(kHeightCount); height++) {
141 break; 140 if (std::bernoulli_distribution(0.5)(rng_)) {
142 } 141 int colour = std::uniform_int_distribution<int>(0, static_cast<int>(kColourCount)-1)(rng_);
143 case kTop: { 142 if (filters.count({static_cast<Height>(height), static_cast<Colour>(colour)})) {
144 forwardFilter &= (verbly::form::pronunciations %= 143 parts[static_cast<Height>(height)] = static_cast<Colour>(colour);
145 verbly::filter("homophones", false, 144 hints++;
146 (verbly::pronunciation::forms %= (wordFilter && verbly::filter(
147 verbly::form::id,
148 verbly::filter::comparison::field_does_not_equal,
149 verbly::form::id)))));
150 break;
151 }
152 default: break; // Not supposed yet.
153 }
154 break;
155 }
156 case kBlack: {
157 switch (height) {
158 case kBottom: {
159 forwardFilter &= (verbly::word::antonyms %= wordFilter);
160 break;
161 }
162 default: break; // Not supposed yet.
163 }
164 break;
165 }
166 case kBrown: {
167 switch (height) {
168 case kBottom: {
169 forwardFilter &= (verbly::notion::causes %= wordFilter);
170 break;
171 }
172 default: break; // Not supposed yet.
173 }
174 break;
175 }
176 case kRed: {
177 switch (height) {
178 case kTop: {
179 forwardFilter &= (verbly::pronunciation::holophones %= wordFilter);
180 break;
181 }
182 case kMiddle: {
183 forwardFilter &= (verbly::form::holographs %= wordFilter);
184 break;
185 }
186 case kBottom: {
187 forwardFilter &= (verbly::notion::partMeronyms %= wordFilter);
188 break;
189 }
190 default: break; // Not supposed yet.
191 }
192 break;
193 }
194 case kBlue: {
195 switch (height) {
196 case kTop: {
197 forwardFilter &= (verbly::pronunciation::merophones %= wordFilter);
198 break;
199 }
200 case kMiddle: {
201 forwardFilter &= (verbly::form::merographs %= wordFilter);
202 break;
203 }
204 case kBottom: {
205 forwardFilter &= (verbly::notion::partHolonyms %= wordFilter);
206 break;
207 }
208 default: break; // Not supposed yet.
209 }
210 break;
211 }
212 case kPurple: {
213 switch (height) {
214 case kMiddle: {
215 forwardFilter &= (verbly::form::merographs %= (verbly::form::length >= 4 && (verbly::form::holographs %= wordFilter)));
216 break;
217 }
218 case kTop: {
219 forwardFilter &= (verbly::pronunciation::rhymes %= wordFilter);
220 break;
221 }
222 default: break; // Not supposed yet.
223 }
224 break;
225 }
226 case kYellow: {
227 switch (height) {
228 case kTop: {
229 forwardFilter &= (verbly::pronunciation::anaphones %= (wordFilter && verbly::filter(
230 verbly::pronunciation::id,
231 verbly::filter::comparison::field_does_not_equal,
232 verbly::pronunciation::id)));
233 break;
234 }
235 case kMiddle: {
236 forwardFilter &= (verbly::form::anagrams %= (wordFilter && verbly::filter(
237 verbly::form::id,
238 verbly::filter::comparison::field_does_not_equal,
239 verbly::form::id)));
240 break;
241 }
242 default: break; // Not supposed yet.
243 } 145 }
244 break;
245 } 146 }
246 default: break; // Not supposed yet.
247 } 147 }
248 }
249 148
250 verbly::form solution = database.forms(forwardFilter).first(); 149 if (hints < 2) {
150 continue;
151 }
251 152
252 std::ostringstream msg_stream; 153 verbly::filter forwardFilter = cleanFilter && (verbly::form::proper == false);
253 for (int i=0; i<static_cast<int>(kHeightCount); i++) { 154 for (int i=0; i<static_cast<int>(kHeightCount); i++) {
254 Height height = static_cast<Height>(i); 155 Height height = static_cast<Height>(i);
255 std::optional<Colour>& colour = parts[i]; 156 std::optional<Colour>& colour = parts[i];
256 if (colour.has_value()) { 157 if (!colour.has_value()) {
257 verbly::filter questionFilter; 158 continue;
159 }
258 switch (*colour) { 160 switch (*colour) {
259 case kWhite: { 161 case kWhite: {
260 switch (height) { 162 switch (height) {
261 case kBottom: { 163 case kBottom: {
262 questionFilter = (verbly::word::synonyms %= solution); 164 forwardFilter &= (verbly::word::synonyms %= wordFilter);
263 break; 165 break;
264 } 166 }
265 case kTop: { 167 case kTop: {
266 questionFilter = (verbly::form::pronunciations %= 168 forwardFilter &= (verbly::form::pronunciations %=
267 verbly::filter("homophones", false, 169 verbly::filter("homophones", false,
268 (verbly::pronunciation::forms %= ((verbly::filter)solution && verbly::filter( 170 (verbly::pronunciation::forms %= (wordFilter && verbly::filter(
269 verbly::form::id, 171 verbly::form::id,
270 verbly::filter::comparison::field_does_not_equal, 172 verbly::filter::comparison::field_does_not_equal,
271 verbly::form::id))))); 173 verbly::form::id)))));
@@ -278,7 +180,7 @@ int main(int argc, char** argv)
278 case kBlack: { 180 case kBlack: {
279 switch (height) { 181 switch (height) {
280 case kBottom: { 182 case kBottom: {
281 questionFilter = (verbly::word::antonyms %= solution); 183 forwardFilter &= (verbly::word::antonyms %= wordFilter);
282 break; 184 break;
283 } 185 }
284 default: break; // Not supposed yet. 186 default: break; // Not supposed yet.
@@ -288,51 +190,43 @@ int main(int argc, char** argv)
288 case kBrown: { 190 case kBrown: {
289 switch (height) { 191 switch (height) {
290 case kBottom: { 192 case kBottom: {
291 questionFilter = (verbly::notion::effects %= solution); 193 forwardFilter &= (verbly::notion::causes %= wordFilter);
292 break; 194 break;
293 } 195 }
294 default: break; // Not supposed yet. 196 default: break; // Not supposed yet.
295 } 197 }
296 break; 198 break;
297 } 199 }
298 case kBlue: { 200 case kRed: {
299 switch (height) { 201 switch (height) {
300 case kTop: { 202 case kTop: {
301 questionFilter = (verbly::pronunciation::holophones %= solution); 203 forwardFilter &= (verbly::pronunciation::holophones %= wordFilter);
302 break; 204 break;
303 } 205 }
304 case kMiddle: { 206 case kMiddle: {
305 questionFilter = (verbly::form::holographs %= solution); 207 forwardFilter &= (verbly::form::holographs %= wordFilter);
306 break; 208 break;
307 } 209 }
308 case kBottom: { 210 case kBottom: {
309 /*questionFilter = ((verbly::notion::fullMemberHolonyms %= solution) 211 forwardFilter &= (verbly::notion::partMeronyms %= wordFilter);
310 || (verbly::notion::fullPartHolonyms %= solution)
311 || (verbly::notion::fullSubstanceHolonyms %= solution));*/
312 //questionFilter &= !(verbly::notion::words %= solution);
313 questionFilter = (verbly::notion::partMeronyms %= solution);
314 break; 212 break;
315 } 213 }
316 default: break; // Not supposed yet. 214 default: break; // Not supposed yet.
317 } 215 }
318 break; 216 break;
319 } 217 }
320 case kRed: { 218 case kBlue: {
321 switch (height) { 219 switch (height) {
322 case kTop: { 220 case kTop: {
323 questionFilter = (verbly::pronunciation::merophones %= solution); 221 forwardFilter &= (verbly::pronunciation::merophones %= wordFilter);
324 break; 222 break;
325 } 223 }
326 case kMiddle: { 224 case kMiddle: {
327 questionFilter = (verbly::form::merographs %= solution); 225 forwardFilter &= (verbly::form::merographs %= wordFilter);
328 break; 226 break;
329 } 227 }
330 case kBottom: { 228 case kBottom: {
331 /*questionFilter = ((verbly::notion::fullMemberMeronyms %= solution) 229 forwardFilter &= (verbly::notion::partHolonyms %= wordFilter);
332 || (verbly::notion::fullPartMeronyms %= solution)
333 || (verbly::notion::fullSubstanceMeronyms %= solution));*/
334 questionFilter = (verbly::notion::partHolonyms %= solution);
335 //questionFilter &= !(verbly::notion::words %= solution);
336 break; 230 break;
337 } 231 }
338 default: break; // Not supposed yet. 232 default: break; // Not supposed yet.
@@ -341,12 +235,12 @@ int main(int argc, char** argv)
341 } 235 }
342 case kPurple: { 236 case kPurple: {
343 switch (height) { 237 switch (height) {
344 case kTop: { 238 case kMiddle: {
345 questionFilter = (verbly::pronunciation::rhymes %= solution); 239 forwardFilter &= (verbly::form::merographs %= (verbly::form::length >= 4 && (verbly::form::holographs %= wordFilter)));
346 break; 240 break;
347 } 241 }
348 case kMiddle: { 242 case kTop: {
349 questionFilter = (verbly::form::merographs %= (verbly::form::length >= 4 && (verbly::form::holographs %= solution))); 243 forwardFilter &= (verbly::pronunciation::rhymes %= wordFilter);
350 break; 244 break;
351 } 245 }
352 default: break; // Not supposed yet. 246 default: break; // Not supposed yet.
@@ -356,17 +250,17 @@ int main(int argc, char** argv)
356 case kYellow: { 250 case kYellow: {
357 switch (height) { 251 switch (height) {
358 case kTop: { 252 case kTop: {
359 questionFilter = (verbly::pronunciation::anaphones %= ((verbly::filter)solution && verbly::filter( 253 forwardFilter &= (verbly::pronunciation::anaphones %= (wordFilter && verbly::filter(
360 verbly::pronunciation::id, 254 verbly::pronunciation::id,
361 verbly::filter::comparison::field_does_not_equal, 255 verbly::filter::comparison::field_does_not_equal,
362 verbly::pronunciation::id))); 256 verbly::pronunciation::id)));
363 break; 257 break;
364 } 258 }
365 case kMiddle: { 259 case kMiddle: {
366 questionFilter = (verbly::form::anagrams %= ((verbly::filter)solution && verbly::filter( 260 forwardFilter &= (verbly::form::anagrams %= (wordFilter && verbly::filter(
367 verbly::form::id, 261 verbly::form::id,
368 verbly::filter::comparison::field_does_not_equal, 262 verbly::filter::comparison::field_does_not_equal,
369 verbly::form::id))); 263 verbly::form::id)));
370 break; 264 break;
371 } 265 }
372 default: break; // Not supposed yet. 266 default: break; // Not supposed yet.
@@ -375,33 +269,187 @@ int main(int argc, char** argv)
375 } 269 }
376 default: break; // Not supposed yet. 270 default: break; // Not supposed yet.
377 } 271 }
378 verbly::form questionPart = database.forms(questionFilter && cleanFilter).first();
379 msg_stream << COLOUR_EMOJIS[*colour] << " " << questionPart.getText() << std::endl;
380 } else {
381 msg_stream << "▪️" << std::endl;
382 } 272 }
383 }
384 msg_stream << "(" << solution.getText().size() << ")";
385 273
386 std::string message_text = msg_stream.str(); 274 verbly::form solution = database_->forms(forwardFilter).first();
387 std::cout << message_text << std::endl << std::endl << solution.getText() << std::endl;
388 275
389 dpp::message message(channel, message_text); 276 std::ostringstream msg_stream;
390 bot.message_create(message, [&answers_mutex, &answer_by_message, &solution](const dpp::confirmation_callback_t& userdata) { 277 for (int i=0; i<static_cast<int>(kHeightCount); i++) {
391 const auto& posted_msg = std::get<dpp::message>(userdata.value); 278 Height height = static_cast<Height>(i);
392 std::lock_guard answer_lock(answers_mutex); 279 std::optional<Colour>& colour = parts[i];
393 if (answer_by_message.size() > 3000) 280 if (colour.has_value()) {
394 { 281 verbly::filter questionFilter;
395 answer_by_message.clear(); 282 switch (*colour) {
283 case kWhite: {
284 switch (height) {
285 case kBottom: {
286 questionFilter = (verbly::word::synonyms %= solution);
287 break;
288 }
289 case kTop: {
290 questionFilter = (verbly::form::pronunciations %=
291 verbly::filter("homophones", false,
292 (verbly::pronunciation::forms %= ((verbly::filter)solution && verbly::filter(
293 verbly::form::id,
294 verbly::filter::comparison::field_does_not_equal,
295 verbly::form::id)))));
296 break;
297 }
298 default: break; // Not supposed yet.
299 }
300 break;
301 }
302 case kBlack: {
303 switch (height) {
304 case kBottom: {
305 questionFilter = (verbly::word::antonyms %= solution);
306 break;
307 }
308 default: break; // Not supposed yet.
309 }
310 break;
311 }
312 case kBrown: {
313 switch (height) {
314 case kBottom: {
315 questionFilter = (verbly::notion::effects %= solution);
316 break;
317 }
318 default: break; // Not supposed yet.
319 }
320 break;
321 }
322 case kBlue: {
323 switch (height) {
324 case kTop: {
325 questionFilter = (verbly::pronunciation::holophones %= solution);
326 break;
327 }
328 case kMiddle: {
329 questionFilter = (verbly::form::holographs %= solution);
330 break;
331 }
332 case kBottom: {
333 /*questionFilter = ((verbly::notion::fullMemberHolonyms %= solution)
334 || (verbly::notion::fullPartHolonyms %= solution)
335 || (verbly::notion::fullSubstanceHolonyms %= solution));*/
336 //questionFilter &= !(verbly::notion::words %= solution);
337 questionFilter = (verbly::notion::partMeronyms %= solution);
338 break;
339 }
340 default: break; // Not supposed yet.
341 }
342 break;
343 }
344 case kRed: {
345 switch (height) {
346 case kTop: {
347 questionFilter = (verbly::pronunciation::merophones %= solution);
348 break;
349 }
350 case kMiddle: {
351 questionFilter = (verbly::form::merographs %= solution);
352 break;
353 }
354 case kBottom: {
355 /*questionFilter = ((verbly::notion::fullMemberMeronyms %= solution)
356 || (verbly::notion::fullPartMeronyms %= solution)
357 || (verbly::notion::fullSubstanceMeronyms %= solution));*/
358 questionFilter = (verbly::notion::partHolonyms %= solution);
359 //questionFilter &= !(verbly::notion::words %= solution);
360 break;
361 }
362 default: break; // Not supposed yet.
363 }
364 break;
365 }
366 case kPurple: {
367 switch (height) {
368 case kTop: {
369 questionFilter = (verbly::pronunciation::rhymes %= solution);
370 break;
371 }
372 case kMiddle: {
373 questionFilter = (verbly::form::merographs %= (verbly::form::length >= 4 && (verbly::form::holographs %= solution)));
374 break;
375 }
376 default: break; // Not supposed yet.
377 }
378 break;
379 }
380 case kYellow: {
381 switch (height) {
382 case kTop: {
383 questionFilter = (verbly::pronunciation::anaphones %= ((verbly::filter)solution && verbly::filter(
384 verbly::pronunciation::id,
385 verbly::filter::comparison::field_does_not_equal,
386 verbly::pronunciation::id)));
387 break;
388 }
389 case kMiddle: {
390 questionFilter = (verbly::form::anagrams %= ((verbly::filter)solution && verbly::filter(
391 verbly::form::id,
392 verbly::filter::comparison::field_does_not_equal,
393 verbly::form::id)));
394 break;
395 }
396 default: break; // Not supposed yet.
397 }
398 break;
399 }
400 default: break; // Not supposed yet.
401 }
402 verbly::form questionPart = database_->forms(questionFilter && cleanFilter).first();
403 msg_stream << COLOUR_EMOJIS[*colour] << " " << questionPart.getText() << std::endl;
404 } else {
405 msg_stream << "▪️" << std::endl;
406 }
396 } 407 }
397 answer_by_message[posted_msg.id] = solution.getText(); 408 msg_stream << "(" << solution.getText().size() << ")";
398 }); 409
410 std::string message_text = msg_stream.str();
411 std::cout << message_text << std::endl << std::endl << solution.getText() << std::endl;
399 412
400 std::this_thread::sleep_for(std::chrono::hours(3)); 413 dpp::message message(channel, message_text);
401 } catch (const std::exception& ex) { 414 bot_->message_create(message, [this, &solution](const dpp::confirmation_callback_t& userdata) {
402 std::cout << ex.what() << std::endl; 415 const auto& posted_msg = std::get<dpp::message>(userdata.value);
416 std::lock_guard answer_lock(answers_mutex_);
417 if (answer_by_message_.size() > 3000)
418 {
419 answer_by_message_.clear();
420 }
421 answer_by_message_[posted_msg.id] = solution.getText();
422 });
423
424 generated = true;
425 } catch (const std::exception& ex) {
426 std::cout << ex.what() << std::endl;
427 }
428
429 std::this_thread::sleep_for(std::chrono::minutes(1));
403 } 430 }
431 }
432
433 std::mt19937& rng_;
434 std::unique_ptr<dpp::cluster> bot_;
435 std::unique_ptr<verbly::database> database_;
436 std::map<uint64_t, std::string> answer_by_message_;
437 std::mutex answers_mutex_;
438};
439
440int main(int argc, char** argv)
441{
442 std::random_device randomDevice;
443 std::mt19937 rng{randomDevice()};
404 444
405 std::this_thread::sleep_for(std::chrono::minutes(1)); 445 if (argc != 2)
446 {
447 std::cout << "usage: lingo [configfile]" << std::endl;
448 return -1;
406 } 449 }
450
451 lingo lingo(rng);
452 lingo.run(argv[1]);
453
454 return 0;
407} 455}