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.cpp273
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
15enum Height {
16 kTop,
17 kMiddle,
18 kBottom,
19 kHeightCount
20};
21
22enum Colour {
23 kWhite,
24 kBlack,
25 kRed,
26 kBlue,
27 kPurple,
28 kBrown,
29 kColourCount
30};
31
32const std::string COLOUR_EMOJIS[kColourCount] = {
33 "⬜️",
34 "⬛️",
35 "🟥",
36 "🟦",
37 "🟪",
38 "🟫"
39};
40
41int 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}