summary refs log tree commit diff stats
path: root/infinite.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'infinite.cpp')
-rw-r--r--infinite.cpp772
1 files changed, 772 insertions, 0 deletions
diff --git a/infinite.cpp b/infinite.cpp new file mode 100644 index 0000000..bf09fe2 --- /dev/null +++ b/infinite.cpp
@@ -0,0 +1,772 @@
1#include "fractal.h"
2#include <Magick++.h>
3#include <ctime>
4#include <cstdio>
5#include <iostream>
6#include <verbly.h>
7#include <fstream>
8#include <dirent.h>
9#include <yaml-cpp/yaml.h>
10#include <unistd.h>
11#include <twitter.h>
12
13class fill_blanks {
14 private:
15 verbly::data& database;
16
17 public:
18 fill_blanks(verbly::data& database) : database(database)
19 {
20
21 }
22
23 verbly::filter<verbly::noun> parse_selrestrs(verbly::frame::selrestr selrestr)
24 {
25 switch (selrestr.get_type())
26 {
27 case verbly::frame::selrestr::type::empty:
28 {
29 return verbly::filter<verbly::noun>{};
30 }
31
32 case verbly::frame::selrestr::type::singleton:
33 {
34 verbly::noun n;
35
36 if (selrestr.get_restriction() == "concrete")
37 {
38 n = database.nouns().with_singular_form("physical entity").limit(1).run().front();
39 } else if (selrestr.get_restriction() == "time")
40 {
41 n = database.nouns().with_singular_form("time").limit(1).run().front();
42 } else if (selrestr.get_restriction() == "state")
43 {
44 n = database.nouns().with_singular_form("state").limit(1).run().front();
45 } else if (selrestr.get_restriction() == "abstract")
46 {
47 n = database.nouns().with_singular_form("abstract entity").limit(1).run().front();
48 } else if (selrestr.get_restriction() == "time")
49 {
50 n = database.nouns().with_singular_form("time").limit(1).run().front();
51 } else if (selrestr.get_restriction() == "scalar")
52 {
53 n = database.nouns().with_singular_form("number").limit(1).run().front();
54 } else if (selrestr.get_restriction() == "currency")
55 {
56 auto nn2 = database.nouns().with_singular_form("currency").limit(2).run();
57 std::vector<verbly::noun> nn(std::begin(nn2), std::end(nn2));
58 n = nn[1];
59 } else if (selrestr.get_restriction() == "location")
60 {
61 n = database.nouns().with_singular_form("location").limit(1).run().front();
62 } else if (selrestr.get_restriction() == "organization")
63 {
64 n = database.nouns().with_singular_form("organization").limit(1).run().front();
65 } else if (selrestr.get_restriction() == "int_control")
66 {
67 n = database.nouns().with_singular_form("causal agent").limit(1).run().front();
68 } else if (selrestr.get_restriction() == "natural")
69 {
70 n = database.nouns().with_singular_form("natural object").limit(1).run().front();
71 } else if (selrestr.get_restriction() == "phys_obj")
72 {
73 n = database.nouns().with_singular_form("physical object").limit(1).run().front();
74 } else if (selrestr.get_restriction() == "solid")
75 {
76 n = database.nouns().with_singular_form("solid").limit(1).run().front();
77 } else if (selrestr.get_restriction() == "shape")
78 {
79 n = database.nouns().with_singular_form("shape").limit(1).run().front();
80 } else if (selrestr.get_restriction() == "substance")
81 {
82 n = database.nouns().with_singular_form("substance").limit(1).run().front();
83 } else if (selrestr.get_restriction() == "idea")
84 {
85 n = database.nouns().with_singular_form("idea").limit(1).run().front();
86 } else if (selrestr.get_restriction() == "sound")
87 {
88 auto nn2 = database.nouns().with_singular_form("sound").limit(4).run();
89 std::vector<verbly::noun> nn(std::begin(nn2), std::end(nn2));
90 n = nn[3];
91 } else if (selrestr.get_restriction() == "communication")
92 {
93 n = database.nouns().with_singular_form("communication").limit(1).run().front();
94 } else if (selrestr.get_restriction() == "region")
95 {
96 n = database.nouns().with_singular_form("region").limit(1).run().front();
97 } else if (selrestr.get_restriction() == "place")
98 {
99 n = database.nouns().with_singular_form("place").limit(1).run().front();
100 } else if (selrestr.get_restriction() == "machine")
101 {
102 n = database.nouns().with_singular_form("machine").limit(1).run().front();
103 } else if (selrestr.get_restriction() == "animate")
104 {
105 n = database.nouns().with_singular_form("animate being").limit(1).run().front();
106 } else if (selrestr.get_restriction() == "plant")
107 {
108 auto nn2 = database.nouns().with_singular_form("plant").limit(2).run();
109 std::vector<verbly::noun> nn(std::begin(nn2), std::end(nn2));
110 n = nn[1];
111 } else if (selrestr.get_restriction() == "comestible")
112 {
113 n = database.nouns().with_singular_form("food").limit(1).run().front();
114 } else if (selrestr.get_restriction() == "artifact")
115 {
116 n = database.nouns().with_singular_form("artifact").limit(1).run().front();
117 } else if (selrestr.get_restriction() == "vehicle")
118 {
119 n = database.nouns().with_singular_form("vehicle").limit(1).run().front();
120 } else if (selrestr.get_restriction() == "human")
121 {
122 n = database.nouns().with_singular_form("person").limit(1).run().front();
123 } else if (selrestr.get_restriction() == "animal")
124 {
125 n = database.nouns().with_singular_form("animal").limit(1).run().front();
126 } else if (selrestr.get_restriction() == "body_part")
127 {
128 n = database.nouns().with_singular_form("body part").limit(1).run().front();
129 } else if (selrestr.get_restriction() == "garment")
130 {
131 n = database.nouns().with_singular_form("clothing").limit(1).run().front();
132 } else if (selrestr.get_restriction() == "tool")
133 {
134 n = database.nouns().with_singular_form("tool").limit(1).run().front();
135 } else {
136 return verbly::filter<verbly::noun>{};
137 }
138
139 return verbly::filter<verbly::noun>{n, !selrestr.get_pos()};
140 }
141
142 case verbly::frame::selrestr::type::group:
143 {
144 verbly::filter<verbly::noun> ret;
145 ret.set_orlogic(selrestr.get_orlogic());
146
147 std::transform(std::begin(selrestr), std::end(selrestr), std::back_inserter(ret), [&] (verbly::frame::selrestr sr) {
148 return parse_selrestrs(sr);
149 });
150
151 return ret;
152 }
153 }
154 }
155
156 void visit(verbly::token& it)
157 {
158 switch (it.get_type())
159 {
160 case verbly::token::type::utterance:
161 {
162 for (auto& tkn : it)
163 {
164 if (!tkn.is_complete())
165 {
166 visit(tkn);
167
168 break;
169 }
170 }
171
172 break;
173 }
174
175 case verbly::token::type::fillin:
176 {
177 switch (it.get_fillin_type())
178 {
179 case verbly::token::fillin_type::participle_phrase:
180 {
181 for (;;)
182 {
183 verbly::verb v = database.verbs().has_frames().random().limit(1).run().front();
184 auto frames = v.frames().run();
185 std::vector<verbly::frame> filtered;
186 std::remove_copy_if(std::begin(frames), std::end(frames), std::back_inserter(filtered), [] (verbly::frame& f) {
187 if (f.parts().size() < 2)
188 {
189 return true;
190 }
191
192 if (f.parts()[0].get_type() != verbly::frame::part::type::noun_phrase)
193 {
194 return true;
195 }
196
197 if (f.parts()[0].get_role() != "Agent")
198 {
199 return true;
200 }
201
202 if (f.parts()[1].get_type() != verbly::frame::part::type::verb)
203 {
204 return true;
205 }
206
207 return false;
208 });
209
210 if (filtered.empty())
211 {
212 continue;
213 }
214
215 verbly::frame fr = filtered[rand() % filtered.size()];
216 verbly::token utter;
217 for (auto part : fr.parts())
218 {
219 switch (part.get_type())
220 {
221 case verbly::frame::part::type::noun_phrase:
222 {
223 if (part.get_role() == "Agent")
224 {
225 continue;
226 }
227
228 if (part.get_synrestrs().count("adjp") == 1)
229 {
230 utter << verbly::token{verbly::token::fillin_type::adjective_phrase};
231
232 continue;
233 } else if ((part.get_synrestrs().count("be_sc_ing") == 1)
234 || (part.get_synrestrs().count("ac_ing") == 1)
235 || (part.get_synrestrs().count("sc_ing") == 1)
236 || (part.get_synrestrs().count("np_omit_ing") == 1)
237 || (part.get_synrestrs().count("oc_ing") == 1))
238 {
239 utter << verbly::token{verbly::token::fillin_type::participle_phrase};
240
241 continue;
242 } else if ((part.get_synrestrs().count("poss_ing") == 1)
243 || (part.get_synrestrs().count("possing") == 1)
244 || (part.get_synrestrs().count("pos_ing") == 1))
245 {
246 utter << verbly::token{"their"};
247 utter << verbly::token{verbly::token::fillin_type::participle_phrase};
248
249 continue;
250 } else if (part.get_synrestrs().count("genitive") == 1)
251 {
252 utter << verbly::token{"their"};
253
254 continue;
255 } else if (part.get_synrestrs().count("adv_loc") == 1)
256 {
257 if (rand() % 2 == 0)
258 {
259 utter << verbly::token{"here"};
260 } else {
261 utter << verbly::token{"there"};
262 }
263
264 continue;
265 } else if (part.get_synrestrs().count("refl") == 1)
266 {
267 utter << verbly::token{"themselves"};
268
269 continue;
270 } else if ((part.get_synrestrs().count("sc_to_inf") == 1)
271 || (part.get_synrestrs().count("ac_to_inf") == 1)
272 || (part.get_synrestrs().count("vc_to_inf") == 1)
273 || (part.get_synrestrs().count("rs_to_inf") == 1)
274 || (part.get_synrestrs().count("oc_to_inf") == 1))
275 {
276 utter << verbly::token{verbly::token::fillin_type::infinitive_phrase};
277
278 continue;
279 } else if (part.get_synrestrs().count("oc_bare_inf") == 1)
280 {
281 verbly::token tkn{verbly::token::fillin_type::infinitive_phrase};
282 tkn.set_extra(1);
283
284 utter << tkn;
285
286 continue;
287 }
288
289 auto selrestrs = fr.roles()[part.get_role()];
290 auto query = database.nouns().limit(1).random().is_not_proper().full_hyponym_of(parse_selrestrs(selrestrs));
291 verbly::noun n = query.run().front();
292 if ((rand() % 2 == 0) && (part.get_synrestrs().count("definite") == 0))
293 {
294 utter << verbly::token{"the"};
295 } else {
296 if (n.starts_with_vowel_sound())
297 {
298 utter << verbly::token{"an"};
299 } else {
300 utter << verbly::token{"a"};
301 }
302 }
303
304 if (part.get_synrestrs().count("plural") == 1)
305 {
306 utter << verbly::token{n, verbly::token::noun_inflection::plural};
307 } else {
308 utter << verbly::token{n};
309 }
310
311 if (part.get_synrestrs().count("acc_ing") == 1)
312 {
313 utter << verbly::token{verbly::token::fillin_type::participle_phrase};
314 }
315
316 break;
317 }
318
319 case verbly::frame::part::type::verb:
320 {
321 utter << verbly::token{v, verbly::token::verb_inflection::ing_form};
322
323 break;
324 }
325
326 case verbly::frame::part::type::literal_preposition:
327 {
328 utter << verbly::token{part.get_choices()[rand() % part.get_choices().size()]};
329
330 break;
331 }
332
333 case verbly::frame::part::type::selection_preposition:
334 {
335 auto query = database.prepositions();
336 for (auto preprestr : part.get_preprestrs())
337 {
338 query.in_group(preprestr);
339 }
340 utter << verbly::token{query.random().limit(1).run().front()};
341
342 break;
343 }
344
345 case verbly::frame::part::type::adjective:
346 {
347 utter << verbly::token{verbly::token::fillin_type::adjective_phrase};
348
349 break;
350 }
351
352 case verbly::frame::part::type::adverb:
353 {
354 utter << verbly::token{verbly::token::fillin_type::adverb_phrase};
355
356 break;
357 }
358
359 case verbly::frame::part::type::literal:
360 {
361 utter << verbly::token{part.get_literal()};
362
363 break;
364 }
365 }
366 }
367
368 it = utter;
369
370 break;
371 }
372
373 break;
374 }
375
376 case verbly::token::fillin_type::adjective_phrase:
377 {
378 verbly::token phrase;
379
380 if (rand() % 4 == 0)
381 {
382 phrase << verbly::token{verbly::token::fillin_type::adverb_phrase};
383 }
384
385 if (rand() % 2 == 0)
386 {
387 phrase << verbly::token{verbly::token::fillin_type::participle_phrase};
388 } else {
389 phrase << verbly::token{database.adjectives().random().limit(1).run().front()};
390 }
391
392 it = phrase;
393
394 break;
395 }
396
397 case verbly::token::fillin_type::adverb_phrase:
398 {
399 it = verbly::token{database.adverbs().random().limit(1).run().front()};
400
401 break;
402 }
403
404 case verbly::token::fillin_type::infinitive_phrase:
405 {
406 verbly::token utter;
407 if (it.get_extra() != 1)
408 {
409 utter << verbly::token{"to"};
410 }
411
412 utter << verbly::token{database.verbs().random().limit(1).run().front()};
413
414 it = utter;
415
416 break;
417 }
418
419 default:
420 {
421 it = verbly::token{"*the reality of the situation*"};
422
423 break;
424 }
425 }
426
427 break;
428 }
429 }
430 }
431};
432
433int main(int argc, char** argv)
434{
435 srand(time(NULL));
436 Magick::InitializeMagick(nullptr);
437
438 int delay = 60 * 60;
439
440 YAML::Node config = YAML::LoadFile("config.yml");
441 twitter::auth auth;
442 auth.setConsumerKey(config["consumer_key"].as<std::string>());
443 auth.setConsumerSecret(config["consumer_secret"].as<std::string>());
444 auth.setAccessKey(config["access_key"].as<std::string>());
445 auth.setAccessSecret(config["access_secret"].as<std::string>());
446
447 twitter::client client(auth);
448
449 for (;;)
450 {
451 std::cout << "Generating text..." << std::endl;
452
453 std::vector<std::string> forms;
454 std::ifstream datafile("forms.txt");
455 if (!datafile.is_open())
456 {
457 std::cout << "Could not find forms.txt" << std::endl;
458 return 1;
459 }
460
461 std::string line;
462 while (getline(datafile, line))
463 {
464 if (line.back() == '\r')
465 {
466 line.pop_back();
467 }
468
469 forms.push_back(line);
470 }
471
472 datafile.close();
473
474 verbly::data database {"data.sqlite3"};
475 std::string action = forms[rand() % forms.size()];
476 int tknloc;
477 while ((tknloc = action.find("{")) != std::string::npos)
478 {
479 std::string token = action.substr(tknloc+1, action.find("}")-tknloc-1);
480
481 std::string canontkn;
482 std::transform(std::begin(token), std::end(token), std::back_inserter(canontkn), [] (char ch) {
483 return std::toupper(ch);
484 });
485
486 std::string result;
487 if (canontkn == "NOUN")
488 {
489 result = database.nouns().is_not_proper().random().limit(1).with_complexity(1).run().front().singular_form();
490 } else if (canontkn == "PLURAL_NOUN")
491 {
492 result = database.nouns().is_not_proper().requires_plural_form().random().limit(1).with_complexity(1).run().front().plural_form();
493 } else if (canontkn == "ADJECTIVE")
494 {
495 result = database.adjectives().with_complexity(1).random().limit(1).run().front().base_form();
496 } else if (canontkn == "VERB")
497 {
498 result = database.verbs().random().limit(1).run().front().infinitive_form();
499 } else if (canontkn == "VERBED")
500 {
501 result = database.verbs().random().limit(1).run().front().past_tense_form();
502 } else if (canontkn == "VERBS")
503 {
504 result = database.verbs().random().limit(1).run().front().s_form();
505 } else if (canontkn == "VERBING")
506 {
507 result = database.verbs().random().limit(1).run().front().ing_form();
508 } else if (canontkn == "LOCATION")
509 {
510 auto hem1 = database.nouns().with_singular_form("eastern hemisphere").limit(1).run().front();
511 auto hem2 = database.nouns().with_singular_form("western hemisphere").limit(1).run().front();
512 verbly::filter<verbly::noun> region{hem1, hem2};
513 region.set_orlogic(true);
514
515 result = database.nouns().full_part_holonym_of(region).random().limit(1).run().front().singular_form();
516 } else if (canontkn == "LANGUAGE")
517 {
518 auto natlan = database.nouns().with_singular_form("natural language").limit(1).run().front();
519 result = database.nouns().full_hyponym_of(natlan).is_proper().random().limit(1).run().front().singular_form();
520 } else if (canontkn == "ADVERB")
521 {
522 result = database.adverbs().with_complexity(1).random().limit(1).run().front().base_form();
523 } else if (canontkn == "SENTENCE")
524 {
525 fill_blanks yeah {database};
526 verbly::token action{
527 {"I am"},
528 {verbly::token::fillin_type::adjective_phrase}
529 };
530 while (!action.is_complete())
531 {
532 yeah.visit(action);
533 }
534 result = action.compile();
535 }
536
537 std::string finalresult;
538 if (islower(token[0]))
539 {
540 std::transform(std::begin(result), std::end(result), std::back_inserter(finalresult), [] (char ch) {
541 return std::tolower(ch);
542 });
543 } else if (isupper(token[0]) && !isupper(token[1]))
544 {
545 auto words = verbly::split<std::list<std::string>>(result, " ");
546 for (auto& word : words)
547 {
548 word[0] = std::toupper(word[0]);
549 }
550
551 finalresult = verbly::implode(std::begin(words), std::end(words), " ");
552 } else {
553 finalresult = result;
554 }
555
556 action.replace(tknloc, action.find("}")-tknloc+1, finalresult);
557 }
558
559 double zoom = 2.0;
560 double target_w = 1280;
561 double target_h = 800;
562 double sample_rate = 3;
563
564 std::cout << "Generating flame fractal..." << std::endl;
565
566 Magick::Image image(Magick::Geometry(target_w, target_h), "black");
567 image.type(Magick::TrueColorMatteType);
568
569 for (;;)
570 {
571 Fractal fractal = Fractal::random();
572 std::vector<Color> irradiance(target_w*target_h*sample_rate*sample_rate, Color(0.0, 0.0, 0.0, 0.0));
573
574 double x = (double)rand()/(double)RAND_MAX*2.0-1.0;
575 double y = (double)rand()/(double)RAND_MAX*2.0-1.0;
576 double c = (double)rand()/RAND_MAX;
577
578 double widthmul = fractal.width/target_w*zoom;
579 double heightmul = fractal.height/target_w*zoom;
580 double widthmul2 = widthmul * 2.0;
581 double heightmul2 = heightmul * 2.0;
582
583 int maxrad = 0;
584 for (int i=0; i<50000000; i++)
585 {
586 fractal.sample(x, y, c);
587
588 int fx = (x+widthmul)/widthmul2*target_w*sample_rate;
589 int fy = (y+heightmul)/heightmul2*target_h*sample_rate;
590
591 if (fx >= 0 && fx < target_w*sample_rate && fy >= 0 && fy < target_h*sample_rate && i > 20)
592 {
593 auto& irr = irradiance[fx+fy*target_w*sample_rate];
594 irr += fractal.get_color(c);
595 double alph = irr.a;
596 irr *= 0.5;
597 irr.a = alph;
598
599 if (irr.a > maxrad)
600 {
601 maxrad = irr.a;
602 }
603 }
604 }
605
606 image.modifyImage();
607 Magick::Pixels view(image);
608 Magick::PixelPacket* pixels = view.get(0, 0, target_w, target_h);
609
610 double white = 200.0;
611 double quality = sample_rate*sample_rate;
612 double vibrancy = 1.0;
613 double contrast = 1.0;
614 double brightadjust = 2.3;
615 double k1 = contrast * (268.0 * brightadjust) * 100.0 / fractal.brightness / (256.0*256.0);
616 double k2 = 1.0 / (contrast * white * quality);
617 int covered = 0;
618 for (int j=0; j<target_h; j++)
619 {
620 for (int i=0; i<target_w; i++)
621 {
622 double freq_avg = 0.0;
623 double freq_max = 0.0;
624 Color color_avg(0.0,0.0,0.0,0.0);
625 for (int sy = 0; sy<sample_rate; sy++)
626 {
627 for (int sx = 0; sx<sample_rate; sx++)
628 {
629 auto& fc = irradiance[i*sample_rate+sx+(j*sample_rate+sy)*target_w*sample_rate];
630 freq_avg += fc.a;
631 color_avg += fc;
632 if (fc.a > freq_max)
633 {
634 freq_max = fc.a;
635 }
636 }
637 }
638
639 if (freq_max > 0)
640 {
641 covered++;
642 }
643
644 freq_avg *= (white * fractal.filterlevel)/(sample_rate * sample_rate);
645 color_avg *= (fractal.filterlevel/(sample_rate*sample_rate));
646
647 double alph = k1 * std::log(1+white*freq_avg*k2)/(std::log(10*white*freq_max));
648 double alphg = pow(alph, 1.0/fractal.gamma);
649 if (alph <= fractal.gammathresh)
650 {
651 double frac = alph / fractal.gammathresh;
652 alphg = (1-frac)*alph*pow(fractal.gammathresh, 1.0/fractal.gamma - 1.0) + frac*alphg;
653 }
654
655 double ls = vibrancy*alphg/alph;
656 Color finc = color_avg * ls;
657 finc.a = 1.0;
658
659 if (finc.r > 1.0)
660 {
661 finc *= (1.0 / finc.r);
662 }
663
664 if (finc.g > 1.0)
665 {
666 finc *= (1.0 / finc.g);
667 }
668
669 if (finc.b > 1.0)
670 {
671 finc *= (1.0 / finc.b);
672 }
673
674 *pixels++ = Magick::ColorRGB(finc.r, finc.g, finc.b);
675 }
676 }
677
678 double coverage = ((double)covered/(double)(target_w*target_h));
679 std::cout << coverage << " coverage" << std::endl;
680
681 view.sync();
682
683 if (coverage >= 0.05)
684 {
685 break;
686 }
687
688 std::cout << "Regenerating..." << std::endl;
689 }
690
691 DIR* fontdir;
692 struct dirent* ent;
693 if ((fontdir = opendir("fonts")) == nullptr)
694 {
695 std::cout << "Couldn't find fonts." << std::endl;
696 return -1;
697 }
698
699 std::vector<std::string> fonts;
700 while ((ent = readdir(fontdir)) != nullptr)
701 {
702 std::string dname(ent->d_name);
703 if ((dname.find(".otf") != std::string::npos) || (dname.find(".ttf") != std::string::npos))
704 {
705 fonts.push_back(dname);
706 }
707 }
708
709 closedir(fontdir);
710
711 Magick::Image textimage(Magick::Geometry(target_w, target_h), "transparent");
712 textimage.type(Magick::TrueColorMatteType);
713 textimage.fillColor(Magick::Color("white"));
714 textimage.fontPointsize(72.0);
715 textimage.font("fonts/" + fonts[rand() % fonts.size()]);
716
717 auto words = verbly::split<std::list<std::string>>(action, " ");
718 std::string towrite = "";
719 std::string curline = "";
720 Magick::TypeMetric metric;
721 while (!words.empty())
722 {
723 std::string temp = curline + " " + words.front();
724 textimage.fontTypeMetrics(temp, &metric);
725 if (metric.textWidth() > ((target_w/10)*9))
726 {
727 towrite += "\n" + words.front();
728 curline = words.front();
729 } else {
730 towrite += " " + words.front();
731 curline = temp;
732 }
733
734 words.pop_front();
735 }
736
737 textimage.annotate(towrite, Magick::CenterGravity);
738 textimage.opacity(((double)MaxRGB) * 0.8);
739 image.composite(textimage, 0, 0, Magick::OverCompositeOp);
740
741 image.magick("png");
742
743 Magick::Blob outputimg;
744 image.write(&outputimg);
745
746 std::cout << "Generated image!" << std::endl << "Tweeting..." << std::endl;
747
748 long media_id;
749 twitter::response resp = client.uploadMedia("image/png", (const char*) outputimg.data(), outputimg.length(), media_id);
750 if (resp != twitter::response::ok)
751 {
752 std::cout << "Twitter error while uploading image: " << resp << std::endl;
753 sleep(delay);
754
755 continue;
756 }
757
758 twitter::tweet tw;
759 resp = client.updateStatus("", tw, {media_id});
760 if (resp != twitter::response::ok)
761 {
762 std::cout << "Twitter error while tweeting: " << resp << std::endl;
763 sleep(delay);
764
765 continue;
766 }
767
768 std::cout << "Done!" << std::endl << "Waiting..." << std::endl << std::endl;
769
770 sleep(delay);
771 }
772}