diff options
Diffstat (limited to 'lingo.cpp')
| -rw-r--r-- | lingo.cpp | 273 |
1 files changed, 273 insertions, 0 deletions
| diff --git a/lingo.cpp b/lingo.cpp new file mode 100644 index 0000000..e13bb53 --- /dev/null +++ b/lingo.cpp | |||
| @@ -0,0 +1,273 @@ | |||
| 1 | #include <mastodonpp/mastodonpp.hpp> | ||
| 2 | #include <random> | ||
| 3 | #include <yaml-cpp/yaml.h> | ||
| 4 | #include <iostream> | ||
| 5 | #include <thread> | ||
| 6 | #include <chrono> | ||
| 7 | #include <string> | ||
| 8 | #include <algorithm> | ||
| 9 | #include <verbly.h> | ||
| 10 | #include <json.hpp> | ||
| 11 | #include <optional> | ||
| 12 | #include <map> | ||
| 13 | #include <array> | ||
| 14 | |||
| 15 | enum Height { | ||
| 16 | kTop, | ||
| 17 | kMiddle, | ||
| 18 | kBottom, | ||
| 19 | kHeightCount | ||
| 20 | }; | ||
| 21 | |||
| 22 | enum Colour { | ||
| 23 | kWhite, | ||
| 24 | kBlack, | ||
| 25 | kRed, | ||
| 26 | kBlue, | ||
| 27 | kPurple, | ||
| 28 | kBrown, | ||
| 29 | kColourCount | ||
| 30 | }; | ||
| 31 | |||
| 32 | const std::string COLOUR_EMOJIS[kColourCount] = { | ||
| 33 | "⬜️", | ||
| 34 | "⬛️", | ||
| 35 | "🟥", | ||
| 36 | "🟦", | ||
| 37 | "🟪", | ||
| 38 | "🟫" | ||
| 39 | }; | ||
| 40 | |||
| 41 | int main(int argc, char** argv) | ||
| 42 | { | ||
| 43 | std::random_device randomDevice; | ||
| 44 | std::mt19937 rng{randomDevice()}; | ||
| 45 | |||
| 46 | if (argc != 2) | ||
| 47 | { | ||
| 48 | std::cout << "usage: lingo [configfile]" << std::endl; | ||
| 49 | return -1; | ||
| 50 | } | ||
| 51 | |||
| 52 | std::string configfile(argv[1]); | ||
| 53 | YAML::Node config = YAML::LoadFile(configfile); | ||
| 54 | |||
| 55 | verbly::database database(config["verbly_datafile"].as<std::string>()); | ||
| 56 | |||
| 57 | /*mastodonpp::Instance instance{ | ||
| 58 | config["mastodon_instance"].as<std::string>(), | ||
| 59 | config["mastodon_token"].as<std::string>()}; | ||
| 60 | mastodonpp::Connection connection{instance};*/ | ||
| 61 | |||
| 62 | std::set<std::tuple<Height, Colour>> filters = { | ||
| 63 | {kBottom, kWhite}, | ||
| 64 | {kBottom, kBlack}, | ||
| 65 | {kTop, kPurple}, | ||
| 66 | {kTop, kWhite}, | ||
| 67 | {kBottom, kRed}, | ||
| 68 | {kBottom, kBlue}, | ||
| 69 | }; | ||
| 70 | |||
| 71 | verbly::filter cleanFilter = | ||
| 72 | !(verbly::word::usageDomains %= (verbly::notion::wnid == 106718862)) // ethnic slurs | ||
| 73 | && !(verbly::notion::wnid == 110630093); // "spastic" | ||
| 74 | |||
| 75 | for (;;) | ||
| 76 | { | ||
| 77 | bool puzzleEmpty = true; | ||
| 78 | std::array<std::optional<Colour>, kHeightCount> parts; | ||
| 79 | for (int height = 0; height < static_cast<int>(kHeightCount); height++) { | ||
| 80 | if (std::bernoulli_distribution(0.4)(rng)) { | ||
| 81 | int colour = std::uniform_int_distribution<int>(0, static_cast<int>(kColourCount)-1)(rng); | ||
| 82 | if (filters.count({static_cast<Height>(height), static_cast<Colour>(colour)})) { | ||
| 83 | parts[static_cast<Height>(height)] = static_cast<Colour>(colour); | ||
| 84 | puzzleEmpty = false; | ||
| 85 | } | ||
| 86 | } | ||
| 87 | } | ||
| 88 | |||
| 89 | if (puzzleEmpty) { | ||
| 90 | continue; | ||
| 91 | } | ||
| 92 | |||
| 93 | verbly::filter forwardFilter = cleanFilter && (verbly::form::proper == false); | ||
| 94 | for (int i=0; i<static_cast<int>(kHeightCount); i++) { | ||
| 95 | Height height = static_cast<Height>(i); | ||
| 96 | std::optional<Colour>& colour = parts[i]; | ||
| 97 | if (!colour.has_value()) { | ||
| 98 | continue; | ||
| 99 | } | ||
| 100 | switch (*colour) { | ||
| 101 | case kWhite: { | ||
| 102 | switch (height) { | ||
| 103 | case kBottom: { | ||
| 104 | forwardFilter &= (verbly::word::synonyms); | ||
| 105 | break; | ||
| 106 | } | ||
| 107 | case kTop: { | ||
| 108 | forwardFilter &= (verbly::form::pronunciations %= | ||
| 109 | verbly::filter("homophones", false, | ||
| 110 | (verbly::pronunciation::forms %= verbly::filter( | ||
| 111 | verbly::form::id, | ||
| 112 | verbly::filter::comparison::field_does_not_equal, | ||
| 113 | verbly::form::id)))); | ||
| 114 | break; | ||
| 115 | } | ||
| 116 | default: break; // Not supposed yet. | ||
| 117 | } | ||
| 118 | break; | ||
| 119 | } | ||
| 120 | case kBlack: { | ||
| 121 | switch (height) { | ||
| 122 | case kBottom: { | ||
| 123 | forwardFilter &= (verbly::word::antonyms); | ||
| 124 | break; | ||
| 125 | } | ||
| 126 | default: break; // Not supposed yet. | ||
| 127 | } | ||
| 128 | break; | ||
| 129 | } | ||
| 130 | case kBrown: { | ||
| 131 | switch (height) { | ||
| 132 | case kBottom: { | ||
| 133 | forwardFilter &= (verbly::notion::causes); | ||
| 134 | break; | ||
| 135 | } | ||
| 136 | default: break; // Not supposed yet. | ||
| 137 | } | ||
| 138 | break; | ||
| 139 | } | ||
| 140 | case kRed: { | ||
| 141 | switch (height) { | ||
| 142 | case kBottom: { | ||
| 143 | forwardFilter &= (verbly::notion::partMeronyms); | ||
| 144 | break; | ||
| 145 | } | ||
| 146 | default: break; // Not supposed yet. | ||
| 147 | } | ||
| 148 | break; | ||
| 149 | } | ||
| 150 | case kBlue: { | ||
| 151 | switch (height) { | ||
| 152 | case kBottom: { | ||
| 153 | forwardFilter &= (verbly::notion::partHolonyms); | ||
| 154 | break; | ||
| 155 | } | ||
| 156 | default: break; // Not supposed yet. | ||
| 157 | } | ||
| 158 | break; | ||
| 159 | } | ||
| 160 | case kPurple: { | ||
| 161 | switch (height) { | ||
| 162 | case kTop: { | ||
| 163 | forwardFilter &= (verbly::pronunciation::rhymes); | ||
| 164 | break; | ||
| 165 | } | ||
| 166 | default: break; // Not supposed yet. | ||
| 167 | } | ||
| 168 | break; | ||
| 169 | } | ||
| 170 | default: break; // Not supposed yet. | ||
| 171 | } | ||
| 172 | } | ||
| 173 | |||
| 174 | verbly::word solution = database.words(forwardFilter).first(); | ||
| 175 | |||
| 176 | for (int i=0; i<static_cast<int>(kHeightCount); i++) { | ||
| 177 | Height height = static_cast<Height>(i); | ||
| 178 | std::optional<Colour>& colour = parts[i]; | ||
| 179 | if (colour.has_value()) { | ||
| 180 | verbly::filter questionFilter; | ||
| 181 | switch (*colour) { | ||
| 182 | case kWhite: { | ||
| 183 | switch (height) { | ||
| 184 | case kBottom: { | ||
| 185 | questionFilter = (verbly::word::synonyms %= solution); | ||
| 186 | break; | ||
| 187 | } | ||
| 188 | case kTop: { | ||
| 189 | questionFilter = (verbly::form::pronunciations %= | ||
| 190 | verbly::filter("homophones", false, | ||
| 191 | (verbly::pronunciation::forms %= ((verbly::filter)solution && verbly::filter( | ||
| 192 | verbly::form::id, | ||
| 193 | verbly::filter::comparison::field_does_not_equal, | ||
| 194 | verbly::form::id))))); | ||
| 195 | break; | ||
| 196 | } | ||
| 197 | default: break; // Not supposed yet. | ||
| 198 | } | ||
| 199 | break; | ||
| 200 | } | ||
| 201 | case kBlack: { | ||
| 202 | switch (height) { | ||
| 203 | case kBottom: { | ||
| 204 | questionFilter = (verbly::word::antonyms %= solution); | ||
| 205 | break; | ||
| 206 | } | ||
| 207 | default: break; // Not supposed yet. | ||
| 208 | } | ||
| 209 | break; | ||
| 210 | } | ||
| 211 | case kBrown: { | ||
| 212 | switch (height) { | ||
| 213 | case kBottom: { | ||
| 214 | questionFilter = (verbly::notion::effects %= solution); | ||
| 215 | break; | ||
| 216 | } | ||
| 217 | default: break; // Not supposed yet. | ||
| 218 | } | ||
| 219 | break; | ||
| 220 | } | ||
| 221 | case kBlue: { | ||
| 222 | switch (height) { | ||
| 223 | case kBottom: { | ||
| 224 | /*questionFilter = ((verbly::notion::fullMemberHolonyms %= solution) | ||
| 225 | || (verbly::notion::fullPartHolonyms %= solution) | ||
| 226 | || (verbly::notion::fullSubstanceHolonyms %= solution));*/ | ||
| 227 | //questionFilter &= !(verbly::notion::words %= solution); | ||
| 228 | questionFilter = (verbly::notion::partMeronyms %= solution); | ||
| 229 | break; | ||
| 230 | } | ||
| 231 | default: break; // Not supposed yet. | ||
| 232 | } | ||
| 233 | break; | ||
| 234 | } | ||
| 235 | case kRed: { | ||
| 236 | switch (height) { | ||
| 237 | case kBottom: { | ||
| 238 | /*questionFilter = ((verbly::notion::fullMemberMeronyms %= solution) | ||
| 239 | || (verbly::notion::fullPartMeronyms %= solution) | ||
| 240 | || (verbly::notion::fullSubstanceMeronyms %= solution));*/ | ||
| 241 | questionFilter = (verbly::notion::partHolonyms %= solution); | ||
| 242 | //questionFilter &= !(verbly::notion::words %= solution); | ||
| 243 | break; | ||
| 244 | } | ||
| 245 | default: break; // Not supposed yet. | ||
| 246 | } | ||
| 247 | break; | ||
| 248 | } | ||
| 249 | case kPurple: { | ||
| 250 | switch (height) { | ||
| 251 | case kTop: { | ||
| 252 | questionFilter = (verbly::pronunciation::rhymes %= solution); | ||
| 253 | break; | ||
| 254 | } | ||
| 255 | default: break; // Not supposed yet. | ||
| 256 | } | ||
| 257 | break; | ||
| 258 | } | ||
| 259 | default: break; // Not supposed yet. | ||
| 260 | } | ||
| 261 | verbly::word questionPart = database.words(questionFilter && cleanFilter && (verbly::form::proper == false)).first(); | ||
| 262 | std::cout << COLOUR_EMOJIS[*colour] << " " << questionPart.getBaseForm().getText() << std::endl; | ||
| 263 | } else { | ||
| 264 | std::cout << "▪️" << std::endl; | ||
| 265 | } | ||
| 266 | } | ||
| 267 | std::cout << "(" << solution.getBaseForm().getText().size() << ")" << std::endl << std::endl << solution.getBaseForm().getText() << std::endl; | ||
| 268 | |||
| 269 | |||
| 270 | // We can poll the timeline at most once every five minutes. | ||
| 271 | std::this_thread::sleep_for(std::chrono::hours(3)); | ||
| 272 | } | ||
| 273 | } | ||
