summary refs log tree commit diff stats
path: root/lib
diff options
context:
space:
mode:
authorKelly Rauchenberger <fefferburbia@gmail.com>2016-04-17 13:44:37 -0400
committerKelly Rauchenberger <fefferburbia@gmail.com>2016-04-17 13:44:37 -0400
commit04338f2b040fee5142904c062e0e38c836601034 (patch)
treea3ca42f738839ae4f6c83d599277c33203beb733 /lib
parent040ee58fecdc9c478004bc2e554e1ae126ec4602 (diff)
downloadverbly-04338f2b040fee5142904c062e0e38c836601034.tar.gz
verbly-04338f2b040fee5142904c062e0e38c836601034.tar.bz2
verbly-04338f2b040fee5142904c062e0e38c836601034.zip
Fixed perfect rhyming
Rhyme detection now ensures that any rhymes it finds are perfect rhymes and not identical rhymes. Rhyme detection is also now a lot faster because additional information is stored in the datafile.

Also fixed a bug in the query interface (and the generator) that could cause incorrect queries to be executed.
Diffstat (limited to 'lib')
-rw-r--r--lib/adjective_query.cpp68
-rw-r--r--lib/adjective_query.h10
-rw-r--r--lib/adverb_query.cpp68
-rw-r--r--lib/adverb_query.h10
-rw-r--r--lib/data.cpp2
-rw-r--r--lib/frame_query.cpp2
-rw-r--r--lib/noun_query.cpp73
-rw-r--r--lib/noun_query.h10
-rw-r--r--lib/preposition.cpp2
-rw-r--r--lib/verb_query.cpp68
-rw-r--r--lib/verb_query.h10
-rw-r--r--lib/word.cpp41
-rw-r--r--lib/word.h17
13 files changed, 328 insertions, 53 deletions
diff --git a/lib/adjective_query.cpp b/lib/adjective_query.cpp index a7f915c..2bea68f 100644 --- a/lib/adjective_query.cpp +++ b/lib/adjective_query.cpp
@@ -33,7 +33,7 @@ namespace verbly {
33 33
34 adjective_query& adjective_query::rhymes_with(const word& _word) 34 adjective_query& adjective_query::rhymes_with(const word& _word)
35 { 35 {
36 for (auto rhyme : _word.rhyme_phonemes()) 36 for (auto rhyme : _word.get_rhymes())
37 { 37 {
38 _rhymes.push_back(rhyme); 38 _rhymes.push_back(rhyme);
39 } 39 }
@@ -53,6 +53,34 @@ namespace verbly {
53 return *this; 53 return *this;
54 } 54 }
55 55
56 adjective_query& adjective_query::has_rhyming_noun()
57 {
58 _has_rhyming_noun = true;
59
60 return *this;
61 }
62
63 adjective_query& adjective_query::has_rhyming_adjective()
64 {
65 _has_rhyming_adjective = true;
66
67 return *this;
68 }
69
70 adjective_query& adjective_query::has_rhyming_adverb()
71 {
72 _has_rhyming_adverb = true;
73
74 return *this;
75 }
76
77 adjective_query& adjective_query::has_rhyming_verb()
78 {
79 _has_rhyming_verb = true;
80
81 return *this;
82 }
83
56 adjective_query& adjective_query::with_prefix(filter<std::string> _f) 84 adjective_query& adjective_query::with_prefix(filter<std::string> _f)
57 { 85 {
58 _f.clean(); 86 _f.clean();
@@ -227,16 +255,37 @@ namespace verbly {
227 255
228 if (!_rhymes.empty()) 256 if (!_rhymes.empty())
229 { 257 {
230 std::list<std::string> clauses(_rhymes.size(), "pronunciation LIKE ?"); 258 std::list<std::string> clauses(_rhymes.size(), "(prerhyme != ? AND rhyme = ?)");
231 std::string cond = "adjective_id IN (SELECT adjective_id FROM adjective_pronunciations WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; 259 std::string cond = "adjective_id IN (SELECT adjective_id FROM adjective_pronunciations WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
232 conditions.push_back(cond); 260 conditions.push_back(cond);
233 261
234 for (auto rhyme : _rhymes) 262 for (auto rhy : _rhymes)
235 { 263 {
236 bindings.emplace_back("%" + rhyme); 264 bindings.emplace_back(rhy.get_prerhyme());
265 bindings.emplace_back(rhy.get_rhyme());
237 } 266 }
238 } 267 }
239 268
269 if (_has_rhyming_noun)
270 {
271 conditions.push_back("adjective_id IN (SELECT a.adjective_id FROM adjectives AS a INNER JOIN adjective_pronunciations AS curp ON curp.adjective_id = a.adjective_id INNER JOIN noun_pronunciations AS rhmp ON rhmp.prerhyme != curp.prerhyme AND rhmp.rhyme = curp.rhyme)");
272 }
273
274 if (_has_rhyming_adjective)
275 {
276 conditions.push_back("adjective_id IN (SELECT a.adjective_id FROM adjectives AS a INNER JOIN adjective_pronunciations AS curp ON curp.adjective_id = a.adjective_id INNER JOIN adjective_pronunciations AS rhmp ON rhmp.prerhyme != curp.prerhyme AND rhmp.rhyme = curp.rhyme AND rhmp.adjective_id != curp.adjective_id)");
277 }
278
279 if (_has_rhyming_adverb)
280 {
281 conditions.push_back("adjective_id IN (SELECT a.adjective_id FROM adjectives AS a INNER JOIN adjective_pronunciations AS curp ON curp.adjective_id = a.adjective_id INNER JOIN adverb_pronunciations AS rhmp ON rhmp.prerhyme != curp.prerhyme AND rhmp.rhyme = curp.rhyme)");
282 }
283
284 if (_has_rhyming_verb)
285 {
286 conditions.push_back("adjective_id IN (SELECT a.adjective_id FROM adjectives AS a INNER JOIN adjective_pronunciations AS curp ON curp.adjective_id = a.adjective_id INNER JOIN verb_pronunciations AS rhmp ON rhmp.prerhyme != curp.prerhyme AND rhmp.rhyme = curp.rhyme)");
287 }
288
240 for (auto except : _except) 289 for (auto except : _except)
241 { 290 {
242 conditions.push_back("adjective_id != ?"); 291 conditions.push_back("adjective_id != ?");
@@ -816,7 +865,7 @@ namespace verbly {
816 865
817 case binding::type::string: 866 case binding::type::string:
818 { 867 {
819 sqlite3_bind_text(ppstmt, i, binding.get_string().c_str(), binding.get_string().length(), SQLITE_STATIC); 868 sqlite3_bind_text(ppstmt, i, binding.get_string().c_str(), binding.get_string().length(), SQLITE_TRANSIENT);
820 869
821 break; 870 break;
822 } 871 }
@@ -894,7 +943,7 @@ namespace verbly {
894 943
895 for (auto& adjective : output) 944 for (auto& adjective : output)
896 { 945 {
897 query = "SELECT pronunciation FROM adjective_pronunciations WHERE adjective_id = ?"; 946 query = "SELECT pronunciation, prerhyme, rhyme FROM adjective_pronunciations WHERE adjective_id = ?";
898 if (sqlite3_prepare_v2(_data.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) 947 if (sqlite3_prepare_v2(_data.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK)
899 { 948 {
900 throw std::runtime_error(sqlite3_errmsg(_data.ppdb)); 949 throw std::runtime_error(sqlite3_errmsg(_data.ppdb));
@@ -908,6 +957,13 @@ namespace verbly {
908 auto phonemes = verbly::split<std::list<std::string>>(pronunciation, " "); 957 auto phonemes = verbly::split<std::list<std::string>>(pronunciation, " ");
909 958
910 adjective.pronunciations.push_back(phonemes); 959 adjective.pronunciations.push_back(phonemes);
960
961 if ((sqlite3_column_type(ppstmt, 1) != SQLITE_NULL) && (sqlite3_column_type(ppstmt, 2) != SQLITE_NULL))
962 {
963 std::string prerhyme(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 1)));
964 std::string rhyming(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 2)));
965 adjective.rhymes.emplace_back(prerhyme, rhyming);
966 }
911 } 967 }
912 968
913 sqlite3_finalize(ppstmt); 969 sqlite3_finalize(ppstmt);
diff --git a/lib/adjective_query.h b/lib/adjective_query.h index b2859dc..030a494 100644 --- a/lib/adjective_query.h +++ b/lib/adjective_query.h
@@ -12,6 +12,10 @@ namespace verbly {
12 adjective_query& except(const adjective& _word); 12 adjective_query& except(const adjective& _word);
13 adjective_query& rhymes_with(const word& _word); 13 adjective_query& rhymes_with(const word& _word);
14 adjective_query& has_pronunciation(); 14 adjective_query& has_pronunciation();
15 adjective_query& has_rhyming_noun();
16 adjective_query& has_rhyming_adjective();
17 adjective_query& has_rhyming_adverb();
18 adjective_query& has_rhyming_verb();
15 19
16 adjective_query& requires_comparative_form(); 20 adjective_query& requires_comparative_form();
17 adjective_query& requires_superlative_form(); 21 adjective_query& requires_superlative_form();
@@ -54,9 +58,13 @@ namespace verbly {
54 const data& _data; 58 const data& _data;
55 int _limit = unlimited; 59 int _limit = unlimited;
56 bool _random = false; 60 bool _random = false;
57 std::list<std::string> _rhymes; 61 std::list<rhyme> _rhymes;
58 std::list<adjective> _except; 62 std::list<adjective> _except;
59 bool _has_prn = false; 63 bool _has_prn = false;
64 bool _has_rhyming_noun = false;
65 bool _has_rhyming_adjective = false;
66 bool _has_rhyming_adverb = false;
67 bool _has_rhyming_verb = false;
60 68
61 bool _requires_comparative_form = false; 69 bool _requires_comparative_form = false;
62 bool _requires_superlative_form = false; 70 bool _requires_superlative_form = false;
diff --git a/lib/adverb_query.cpp b/lib/adverb_query.cpp index 30ba92b..797e6a6 100644 --- a/lib/adverb_query.cpp +++ b/lib/adverb_query.cpp
@@ -33,7 +33,7 @@ namespace verbly {
33 33
34 adverb_query& adverb_query::rhymes_with(const word& _word) 34 adverb_query& adverb_query::rhymes_with(const word& _word)
35 { 35 {
36 for (auto rhyme : _word.rhyme_phonemes()) 36 for (auto rhyme : _word.get_rhymes())
37 { 37 {
38 _rhymes.push_back(rhyme); 38 _rhymes.push_back(rhyme);
39 } 39 }
@@ -53,6 +53,34 @@ namespace verbly {
53 return *this; 53 return *this;
54 } 54 }
55 55
56 adverb_query& adverb_query::has_rhyming_noun()
57 {
58 _has_rhyming_noun = true;
59
60 return *this;
61 }
62
63 adverb_query& adverb_query::has_rhyming_adjective()
64 {
65 _has_rhyming_adjective = true;
66
67 return *this;
68 }
69
70 adverb_query& adverb_query::has_rhyming_adverb()
71 {
72 _has_rhyming_adverb = true;
73
74 return *this;
75 }
76
77 adverb_query& adverb_query::has_rhyming_verb()
78 {
79 _has_rhyming_verb = true;
80
81 return *this;
82 }
83
56 adverb_query& adverb_query::requires_comparative_form() 84 adverb_query& adverb_query::requires_comparative_form()
57 { 85 {
58 _requires_comparative_form = true; 86 _requires_comparative_form = true;
@@ -181,16 +209,37 @@ namespace verbly {
181 209
182 if (!_rhymes.empty()) 210 if (!_rhymes.empty())
183 { 211 {
184 std::list<std::string> clauses(_rhymes.size(), "pronunciation LIKE ?"); 212 std::list<std::string> clauses(_rhymes.size(), "(prerhyme != ? AND rhyme = ?)");
185 std::string cond = "adverb_id IN (SELECT adverb_id FROM adverb_pronunciations WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; 213 std::string cond = "adverb_id IN (SELECT adverb_id FROM adverb_pronunciations WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
186 conditions.push_back(cond); 214 conditions.push_back(cond);
187 215
188 for (auto rhyme : _rhymes) 216 for (auto rhy : _rhymes)
189 { 217 {
190 bindings.emplace_back("%" + rhyme); 218 bindings.emplace_back(rhy.get_prerhyme());
219 bindings.emplace_back(rhy.get_rhyme());
191 } 220 }
192 } 221 }
193 222
223 if (_has_rhyming_noun)
224 {
225 conditions.push_back("adverb_id IN (SELECT a.adverb_id FROM adverbs AS a INNER JOIN adverb_pronunciations AS curp ON curp.noun_id = a.adverb_id INNER JOIN noun_pronunciations AS rhmp ON rhmp.prerhyme != curp.prerhyme AND rhmp.rhyme = curp.rhyme)");
226 }
227
228 if (_has_rhyming_adjective)
229 {
230 conditions.push_back("adverb_id IN (SELECT a.adverb_id FROM adverbs AS a INNER JOIN adverb_pronunciations AS curp ON curp.noun_id = a.adverb_id INNER JOIN adjective_pronunciations AS rhmp ON rhmp.prerhyme != curp.prerhyme AND rhmp.rhyme = curp.rhyme)");
231 }
232
233 if (_has_rhyming_adverb)
234 {
235 conditions.push_back("adverb_id IN (SELECT a.adverb_id FROM adverbs AS a INNER JOIN adverb_pronunciations AS curp ON curp.noun_id = a.adverb_id INNER JOIN adverb_pronunciations AS rhmp ON rhmp.prerhyme != curp.prerhyme AND rhmp.rhyme = curp.rhyme AND rhmp.adverb_id != curp.adverb_id)");
236 }
237
238 if (_has_rhyming_verb)
239 {
240 conditions.push_back("adverb_id IN (SELECT a.adverb_id FROM adverbs AS a INNER JOIN adverb_pronunciations AS curp ON curp.noun_id = a.adverb_id INNER JOIN verb_pronunciations AS rhmp ON rhmp.prerhyme != curp.prerhyme AND rhmp.rhyme = curp.rhyme)");
241 }
242
194 for (auto except : _except) 243 for (auto except : _except)
195 { 244 {
196 conditions.push_back("adverb_id != ?"); 245 conditions.push_back("adverb_id != ?");
@@ -538,7 +587,7 @@ namespace verbly {
538 587
539 case binding::type::string: 588 case binding::type::string:
540 { 589 {
541 sqlite3_bind_text(ppstmt, i, binding.get_string().c_str(), binding.get_string().length(), SQLITE_STATIC); 590 sqlite3_bind_text(ppstmt, i, binding.get_string().c_str(), binding.get_string().length(), SQLITE_TRANSIENT);
542 591
543 break; 592 break;
544 } 593 }
@@ -601,7 +650,7 @@ namespace verbly {
601 650
602 for (auto& adverb : output) 651 for (auto& adverb : output)
603 { 652 {
604 query = "SELECT pronunciation FROM adverb_pronunciations WHERE adverb_id = ?"; 653 query = "SELECT pronunciation, prerhyme, rhyme FROM adverb_pronunciations WHERE adverb_id = ?";
605 if (sqlite3_prepare_v2(_data.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) 654 if (sqlite3_prepare_v2(_data.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK)
606 { 655 {
607 throw std::runtime_error(sqlite3_errmsg(_data.ppdb)); 656 throw std::runtime_error(sqlite3_errmsg(_data.ppdb));
@@ -615,6 +664,13 @@ namespace verbly {
615 auto phonemes = verbly::split<std::list<std::string>>(pronunciation, " "); 664 auto phonemes = verbly::split<std::list<std::string>>(pronunciation, " ");
616 665
617 adverb.pronunciations.push_back(phonemes); 666 adverb.pronunciations.push_back(phonemes);
667
668 if ((sqlite3_column_type(ppstmt, 1) != SQLITE_NULL) && (sqlite3_column_type(ppstmt, 2) != SQLITE_NULL))
669 {
670 std::string prerhyme(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 1)));
671 std::string rhyming(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 2)));
672 adverb.rhymes.emplace_back(prerhyme, rhyming);
673 }
618 } 674 }
619 675
620 sqlite3_finalize(ppstmt); 676 sqlite3_finalize(ppstmt);
diff --git a/lib/adverb_query.h b/lib/adverb_query.h index e9354bb..403a616 100644 --- a/lib/adverb_query.h +++ b/lib/adverb_query.h
@@ -12,6 +12,10 @@ namespace verbly {
12 adverb_query& except(const adverb& _word); 12 adverb_query& except(const adverb& _word);
13 adverb_query& rhymes_with(const word& _word); 13 adverb_query& rhymes_with(const word& _word);
14 adverb_query& has_pronunciation(); 14 adverb_query& has_pronunciation();
15 adverb_query& has_rhyming_noun();
16 adverb_query& has_rhyming_adjective();
17 adverb_query& has_rhyming_adverb();
18 adverb_query& has_rhyming_verb();
15 19
16 adverb_query& requires_comparative_form(); 20 adverb_query& requires_comparative_form();
17 adverb_query& requires_superlative_form(); 21 adverb_query& requires_superlative_form();
@@ -41,9 +45,13 @@ namespace verbly {
41 const data& _data; 45 const data& _data;
42 int _limit = unlimited; 46 int _limit = unlimited;
43 bool _random = false; 47 bool _random = false;
44 std::list<std::string> _rhymes; 48 std::list<rhyme> _rhymes;
45 std::list<adverb> _except; 49 std::list<adverb> _except;
46 bool _has_prn = false; 50 bool _has_prn = false;
51 bool _has_rhyming_noun = false;
52 bool _has_rhyming_adjective = false;
53 bool _has_rhyming_adverb = false;
54 bool _has_rhyming_verb = false;
47 55
48 bool _requires_comparative_form = false; 56 bool _requires_comparative_form = false;
49 bool _requires_superlative_form = false; 57 bool _requires_superlative_form = false;
diff --git a/lib/data.cpp b/lib/data.cpp index c14956f..db42487 100644 --- a/lib/data.cpp +++ b/lib/data.cpp
@@ -1,7 +1,7 @@
1#include "verbly.h" 1#include "verbly.h"
2 2
3namespace verbly { 3namespace verbly {
4 4
5 data::data(std::string datafile) 5 data::data(std::string datafile)
6 { 6 {
7 if (sqlite3_open_v2(datafile.c_str(), &ppdb, SQLITE_OPEN_READONLY, NULL) != SQLITE_OK) 7 if (sqlite3_open_v2(datafile.c_str(), &ppdb, SQLITE_OPEN_READONLY, NULL) != SQLITE_OK)
diff --git a/lib/frame_query.cpp b/lib/frame_query.cpp index 3c4a3e8..11f0432 100644 --- a/lib/frame_query.cpp +++ b/lib/frame_query.cpp
@@ -73,7 +73,7 @@ namespace verbly {
73 73
74 case binding::type::string: 74 case binding::type::string:
75 { 75 {
76 sqlite3_bind_text(ppstmt, i, binding.get_string().c_str(), binding.get_string().length(), SQLITE_STATIC); 76 sqlite3_bind_text(ppstmt, i, binding.get_string().c_str(), binding.get_string().length(), SQLITE_TRANSIENT);
77 77
78 break; 78 break;
79 } 79 }
diff --git a/lib/noun_query.cpp b/lib/noun_query.cpp index 19a1297..b4336b6 100644 --- a/lib/noun_query.cpp +++ b/lib/noun_query.cpp
@@ -33,7 +33,7 @@ namespace verbly {
33 33
34 noun_query& noun_query::rhymes_with(const word& _word) 34 noun_query& noun_query::rhymes_with(const word& _word)
35 { 35 {
36 for (auto rhyme : _word.rhyme_phonemes()) 36 for (auto rhyme : _word.get_rhymes())
37 { 37 {
38 _rhymes.push_back(rhyme); 38 _rhymes.push_back(rhyme);
39 } 39 }
@@ -53,6 +53,34 @@ namespace verbly {
53 return *this; 53 return *this;
54 } 54 }
55 55
56 noun_query& noun_query::has_rhyming_noun()
57 {
58 _has_rhyming_noun = true;
59
60 return *this;
61 }
62
63 noun_query& noun_query::has_rhyming_adjective()
64 {
65 _has_rhyming_adjective = true;
66
67 return *this;
68 }
69
70 noun_query& noun_query::has_rhyming_adverb()
71 {
72 _has_rhyming_adverb = true;
73
74 return *this;
75 }
76
77 noun_query& noun_query::has_rhyming_verb()
78 {
79 _has_rhyming_verb = true;
80
81 return *this;
82 }
83
56 noun_query& noun_query::with_singular_form(std::string _arg) 84 noun_query& noun_query::with_singular_form(std::string _arg)
57 { 85 {
58 _with_singular_form.push_back(_arg); 86 _with_singular_form.push_back(_arg);
@@ -483,16 +511,37 @@ namespace verbly {
483 511
484 if (!_rhymes.empty()) 512 if (!_rhymes.empty())
485 { 513 {
486 std::list<std::string> clauses(_rhymes.size(), "pronunciation LIKE ?"); 514 std::list<std::string> clauses(_rhymes.size(), "(prerhyme != ? AND rhyme = ?)");
487 std::string cond = "noun_id IN (SELECT noun_id FROM noun_pronunciations WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; 515 std::string cond = "noun_id IN (SELECT noun_id FROM noun_pronunciations WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
488 conditions.push_back(cond); 516 conditions.push_back(cond);
489 517
490 for (auto rhyme : _rhymes) 518 for (auto rhy : _rhymes)
491 { 519 {
492 bindings.emplace_back("%" + rhyme); 520 bindings.emplace_back(rhy.get_prerhyme());
521 bindings.emplace_back(rhy.get_rhyme());
493 } 522 }
494 } 523 }
495 524
525 if (_has_rhyming_noun)
526 {
527 conditions.push_back("noun_id IN (SELECT a.noun_id FROM nouns AS a INNER JOIN noun_pronunciations AS curp ON curp.noun_id = a.noun_id INNER JOIN noun_pronunciations AS rhmp ON rhmp.prerhyme != curp.prerhyme AND rhmp.rhyme = curp.rhyme AND rhmp.noun_id != curp.noun_id)");
528 }
529
530 if (_has_rhyming_adjective)
531 {
532 conditions.push_back("noun_id IN (SELECT a.noun_id FROM nouns AS a INNER JOIN noun_pronunciations AS curp ON curp.noun_id = a.noun_id INNER JOIN adjective_pronunciations AS rhmp ON rhmp.prerhyme != curp.prerhyme AND rhmp.rhyme = curp.rhyme)");
533 }
534
535 if (_has_rhyming_adverb)
536 {
537 conditions.push_back("noun_id IN (SELECT a.noun_id FROM nouns AS a INNER JOIN noun_pronunciations AS curp ON curp.noun_id = a.noun_id INNER JOIN adverb_pronunciations AS rhmp ON rhmp.prerhyme != curp.prerhyme AND rhmp.rhyme = curp.rhyme)");
538 }
539
540 if (_has_rhyming_verb)
541 {
542 conditions.push_back("noun_id IN (SELECT a.noun_id FROM nouns AS a INNER JOIN noun_pronunciations AS curp ON curp.noun_id = a.noun_id INNER JOIN verb_pronunciations AS rhmp ON rhmp.prerhyme != curp.prerhyme AND rhmp.rhyme = curp.rhyme)");
543 }
544
496 for (auto except : _except) 545 for (auto except : _except)
497 { 546 {
498 conditions.push_back("noun_id != ?"); 547 conditions.push_back("noun_id != ?");
@@ -1768,7 +1817,7 @@ namespace verbly {
1768 { 1817 {
1769 throw std::runtime_error(sqlite3_errmsg(_data.ppdb)); 1818 throw std::runtime_error(sqlite3_errmsg(_data.ppdb));
1770 } 1819 }
1771 1820
1772 int i = 1; 1821 int i = 1;
1773 for (auto& binding : bindings) 1822 for (auto& binding : bindings)
1774 { 1823 {
@@ -1783,7 +1832,7 @@ namespace verbly {
1783 1832
1784 case binding::type::string: 1833 case binding::type::string:
1785 { 1834 {
1786 sqlite3_bind_text(ppstmt, i, binding.get_string().c_str(), binding.get_string().length(), SQLITE_STATIC); 1835 sqlite3_bind_text(ppstmt, i, binding.get_string().c_str(), binding.get_string().length(), SQLITE_TRANSIENT);
1787 1836
1788 break; 1837 break;
1789 } 1838 }
@@ -1791,7 +1840,7 @@ namespace verbly {
1791 1840
1792 i++; 1841 i++;
1793 } 1842 }
1794 1843
1795 /* 1844 /*
1796 for (auto adj : _derived_from_adjective) 1845 for (auto adj : _derived_from_adjective)
1797 { 1846 {
@@ -1843,7 +1892,7 @@ namespace verbly {
1843 1892
1844 for (auto& noun : output) 1893 for (auto& noun : output)
1845 { 1894 {
1846 query = "SELECT pronunciation FROM noun_pronunciations WHERE noun_id = ?"; 1895 query = "SELECT pronunciation, prerhyme, rhyme FROM noun_pronunciations WHERE noun_id = ?";
1847 if (sqlite3_prepare_v2(_data.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) 1896 if (sqlite3_prepare_v2(_data.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK)
1848 { 1897 {
1849 throw std::runtime_error(sqlite3_errmsg(_data.ppdb)); 1898 throw std::runtime_error(sqlite3_errmsg(_data.ppdb));
@@ -1857,6 +1906,14 @@ namespace verbly {
1857 auto phonemes = verbly::split<std::list<std::string>>(pronunciation, " "); 1906 auto phonemes = verbly::split<std::list<std::string>>(pronunciation, " ");
1858 1907
1859 noun.pronunciations.push_back(phonemes); 1908 noun.pronunciations.push_back(phonemes);
1909
1910 if ((sqlite3_column_type(ppstmt, 1) != SQLITE_NULL) && (sqlite3_column_type(ppstmt, 2) != SQLITE_NULL))
1911 {
1912 std::string prerhyme(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 1)));
1913 std::string rhyming(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 2)));
1914
1915 noun.rhymes.emplace_back(prerhyme, rhyming);
1916 }
1860 } 1917 }
1861 1918
1862 sqlite3_finalize(ppstmt); 1919 sqlite3_finalize(ppstmt);
diff --git a/lib/noun_query.h b/lib/noun_query.h index 8768f5d..6b5733f 100644 --- a/lib/noun_query.h +++ b/lib/noun_query.h
@@ -12,6 +12,10 @@ namespace verbly {
12 noun_query& except(const noun& _word); 12 noun_query& except(const noun& _word);
13 noun_query& rhymes_with(const word& _word); 13 noun_query& rhymes_with(const word& _word);
14 noun_query& has_pronunciation(); 14 noun_query& has_pronunciation();
15 noun_query& has_rhyming_noun();
16 noun_query& has_rhyming_adjective();
17 noun_query& has_rhyming_adverb();
18 noun_query& has_rhyming_verb();
15 19
16 noun_query& with_singular_form(std::string _arg); 20 noun_query& with_singular_form(std::string _arg);
17 noun_query& with_prefix(filter<std::string> _f); 21 noun_query& with_prefix(filter<std::string> _f);
@@ -86,9 +90,13 @@ namespace verbly {
86 const data& _data; 90 const data& _data;
87 int _limit = unlimited; 91 int _limit = unlimited;
88 bool _random = false; 92 bool _random = false;
89 std::list<std::string> _rhymes; 93 std::list<rhyme> _rhymes;
90 std::list<noun> _except; 94 std::list<noun> _except;
91 bool _has_prn = false; 95 bool _has_prn = false;
96 bool _has_rhyming_noun = false;
97 bool _has_rhyming_adjective = false;
98 bool _has_rhyming_adverb = false;
99 bool _has_rhyming_verb = false;
92 100
93 std::list<std::string> _with_singular_form; 101 std::list<std::string> _with_singular_form;
94 filter<std::string> _with_prefix; 102 filter<std::string> _with_prefix;
diff --git a/lib/preposition.cpp b/lib/preposition.cpp index 8df13aa..cea9165 100644 --- a/lib/preposition.cpp +++ b/lib/preposition.cpp
@@ -83,7 +83,7 @@ namespace verbly {
83 83
84 case binding::type::string: 84 case binding::type::string:
85 { 85 {
86 sqlite3_bind_text(ppstmt, i, binding.get_string().c_str(), binding.get_string().length(), SQLITE_STATIC); 86 sqlite3_bind_text(ppstmt, i, binding.get_string().c_str(), binding.get_string().length(), SQLITE_TRANSIENT);
87 87
88 break; 88 break;
89 } 89 }
diff --git a/lib/verb_query.cpp b/lib/verb_query.cpp index 929ecc7..654bc33 100644 --- a/lib/verb_query.cpp +++ b/lib/verb_query.cpp
@@ -33,7 +33,7 @@ namespace verbly {
33 33
34 verb_query& verb_query::rhymes_with(const word& _word) 34 verb_query& verb_query::rhymes_with(const word& _word)
35 { 35 {
36 for (auto rhyme : _word.rhyme_phonemes()) 36 for (auto rhyme : _word.get_rhymes())
37 { 37 {
38 _rhymes.push_back(rhyme); 38 _rhymes.push_back(rhyme);
39 } 39 }
@@ -53,6 +53,34 @@ namespace verbly {
53 return *this; 53 return *this;
54 } 54 }
55 55
56 verb_query& verb_query::has_rhyming_noun()
57 {
58 _has_rhyming_noun = true;
59
60 return *this;
61 }
62
63 verb_query& verb_query::has_rhyming_adjective()
64 {
65 _has_rhyming_adjective = true;
66
67 return *this;
68 }
69
70 verb_query& verb_query::has_rhyming_adverb()
71 {
72 _has_rhyming_adverb = true;
73
74 return *this;
75 }
76
77 verb_query& verb_query::has_rhyming_verb()
78 {
79 _has_rhyming_verb = true;
80
81 return *this;
82 }
83
56 verb_query& verb_query::has_frames() 84 verb_query& verb_query::has_frames()
57 { 85 {
58 this->_has_frames = true; 86 this->_has_frames = true;
@@ -74,16 +102,37 @@ namespace verbly {
74 102
75 if (!_rhymes.empty()) 103 if (!_rhymes.empty())
76 { 104 {
77 std::list<std::string> clauses(_rhymes.size(), "pronunciation LIKE ?"); 105 std::list<std::string> clauses(_rhymes.size(), "(prerhyme != ? AND rhyme = ?)");
78 std::string cond = "verb_id IN (SELECT verb_id FROM verb_pronunciations WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; 106 std::string cond = "verb_id IN (SELECT verb_id FROM verb_pronunciations WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
79 conditions.push_back(cond); 107 conditions.push_back(cond);
80 108
81 for (auto rhyme : _rhymes) 109 for (auto rhy : _rhymes)
82 { 110 {
83 bindings.emplace_back("%" + rhyme); 111 bindings.emplace_back(rhy.get_prerhyme());
112 bindings.emplace_back(rhy.get_rhyme());
84 } 113 }
85 } 114 }
86 115
116 if (_has_rhyming_noun)
117 {
118 conditions.push_back("verb_id IN (SELECT a.verb_id FROM verbs AS a INNER JOIN verb_pronunciations AS curp ON curp.noun_id = a.adverb_id INNER JOIN noun_pronunciations AS rhmp ON rhmp.prerhyme != curp.prerhyme AND rhmp.rhyme = curp.rhyme)");
119 }
120
121 if (_has_rhyming_adjective)
122 {
123 conditions.push_back("verb_id IN (SELECT a.verb_id FROM verbs AS a INNER JOIN verb_pronunciations AS curp ON curp.noun_id = a.adverb_id INNER JOIN adjective_pronunciations AS rhmp ON rhmp.prerhyme != curp.prerhyme AND rhmp.rhyme = curp.rhyme)");
124 }
125
126 if (_has_rhyming_adverb)
127 {
128 conditions.push_back("verb_id IN (SELECT a.verb_id FROM verbs AS a INNER JOIN verb_pronunciations AS curp ON curp.noun_id = a.adverb_id INNER JOIN adverb_pronunciations AS rhmp ON rhmp.prerhyme != curp.prerhyme AND rhmp.rhyme = curp.rhyme)");
129 }
130
131 if (_has_rhyming_verb)
132 {
133 conditions.push_back("verb_id IN (SELECT a.verb_id FROM verbs AS a INNER JOIN verb_pronunciations AS curp ON curp.noun_id = a.adverb_id INNER JOIN verb_pronunciations AS rhmp ON rhmp.prerhyme != curp.prerhyme AND rhmp.rhyme = curp.rhyme AND rhmp.verb_id != curp.verb_id)");
134 }
135
87 for (auto except : _except) 136 for (auto except : _except)
88 { 137 {
89 conditions.push_back("verb_id != ?"); 138 conditions.push_back("verb_id != ?");
@@ -132,7 +181,7 @@ namespace verbly {
132 181
133 case binding::type::string: 182 case binding::type::string:
134 { 183 {
135 sqlite3_bind_text(ppstmt, i, binding.get_string().c_str(), binding.get_string().length(), SQLITE_STATIC); 184 sqlite3_bind_text(ppstmt, i, binding.get_string().c_str(), binding.get_string().length(), SQLITE_TRANSIENT);
136 185
137 break; 186 break;
138 } 187 }
@@ -158,7 +207,7 @@ namespace verbly {
158 207
159 for (auto& verb : output) 208 for (auto& verb : output)
160 { 209 {
161 query = "SELECT pronunciation FROM verb_pronunciations WHERE verb_id = ?"; 210 query = "SELECT pronunciation, prerhyme, rhyme FROM verb_pronunciations WHERE verb_id = ?";
162 if (sqlite3_prepare_v2(_data.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) 211 if (sqlite3_prepare_v2(_data.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK)
163 { 212 {
164 throw std::runtime_error(sqlite3_errmsg(_data.ppdb)); 213 throw std::runtime_error(sqlite3_errmsg(_data.ppdb));
@@ -172,6 +221,13 @@ namespace verbly {
172 auto phonemes = verbly::split<std::list<std::string>>(pronunciation, " "); 221 auto phonemes = verbly::split<std::list<std::string>>(pronunciation, " ");
173 222
174 verb.pronunciations.push_back(phonemes); 223 verb.pronunciations.push_back(phonemes);
224
225 if ((sqlite3_column_type(ppstmt, 1) != SQLITE_NULL) && (sqlite3_column_type(ppstmt, 2) != SQLITE_NULL))
226 {
227 std::string prerhyme(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 1)));
228 std::string rhyming(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 2)));
229 verb.rhymes.emplace_back(prerhyme, rhyming);
230 }
175 } 231 }
176 232
177 sqlite3_finalize(ppstmt); 233 sqlite3_finalize(ppstmt);
diff --git a/lib/verb_query.h b/lib/verb_query.h index 24f5732..a07dc18 100644 --- a/lib/verb_query.h +++ b/lib/verb_query.h
@@ -12,6 +12,10 @@ namespace verbly {
12 verb_query& except(const verb& _word); 12 verb_query& except(const verb& _word);
13 verb_query& rhymes_with(const word& _word); 13 verb_query& rhymes_with(const word& _word);
14 verb_query& has_pronunciation(); 14 verb_query& has_pronunciation();
15 verb_query& has_rhyming_noun();
16 verb_query& has_rhyming_adjective();
17 verb_query& has_rhyming_adverb();
18 verb_query& has_rhyming_verb();
15 19
16 verb_query& has_frames(); 20 verb_query& has_frames();
17 21
@@ -23,10 +27,14 @@ namespace verbly {
23 const data& _data; 27 const data& _data;
24 int _limit = unlimited; 28 int _limit = unlimited;
25 bool _random = false; 29 bool _random = false;
26 std::list<std::string> _rhymes; 30 std::list<rhyme> _rhymes;
27 std::list<verb> _except; 31 std::list<verb> _except;
28 bool _has_prn = false; 32 bool _has_prn = false;
29 bool _has_frames = false; 33 bool _has_frames = false;
34 bool _has_rhyming_noun = false;
35 bool _has_rhyming_adjective = false;
36 bool _has_rhyming_adverb = false;
37 bool _has_rhyming_verb = false;
30 }; 38 };
31 39
32}; 40};
diff --git a/lib/word.cpp b/lib/word.cpp index 13c611f..49e34a1 100644 --- a/lib/word.cpp +++ b/lib/word.cpp
@@ -3,6 +3,26 @@
3 3
4namespace verbly { 4namespace verbly {
5 5
6 rhyme::rhyme(std::string prerhyme, std::string phonemes) : _prerhyme(prerhyme), _rhyme(phonemes)
7 {
8
9 }
10
11 std::string rhyme::get_prerhyme() const
12 {
13 return _prerhyme;
14 }
15
16 std::string rhyme::get_rhyme() const
17 {
18 return _rhyme;
19 }
20
21 bool rhyme::operator==(const rhyme& other) const
22 {
23 return std::tie(_prerhyme, _rhyme) == std::tie(other._prerhyme, other._rhyme);
24 }
25
6 word::word() 26 word::word()
7 { 27 {
8 28
@@ -13,28 +33,11 @@ namespace verbly {
13 33
14 } 34 }
15 35
16 std::list<std::string> word::rhyme_phonemes() const 36 std::list<rhyme> word::get_rhymes() const
17 { 37 {
18 assert(_valid == true); 38 assert(_valid == true);
19 39
20 std::list<std::string> result; 40 return rhymes;
21
22 for (auto pronunciation : pronunciations)
23 {
24 auto phemstrt = std::find_if(std::begin(pronunciation), std::end(pronunciation), [] (std::string phoneme) {
25 return phoneme.find("1") != std::string::npos;
26 });
27
28 std::stringstream rhymer;
29 for (auto it = phemstrt; it != std::end(pronunciation); it++)
30 {
31 rhymer << " " << *it;
32 }
33
34 result.push_back(rhymer.str());
35 }
36
37 return result;
38 } 41 }
39 42
40 bool word::starts_with_vowel_sound() const 43 bool word::starts_with_vowel_sound() const
diff --git a/lib/word.h b/lib/word.h index dc6fac8..08797a3 100644 --- a/lib/word.h +++ b/lib/word.h
@@ -3,6 +3,20 @@
3 3
4namespace verbly { 4namespace verbly {
5 5
6 class rhyme {
7 public:
8 rhyme(std::string prerhyme, std::string phonemes);
9
10 std::string get_prerhyme() const;
11 std::string get_rhyme() const;
12
13 bool operator==(const rhyme& other) const;
14
15 private:
16 std::string _prerhyme;
17 std::string _rhyme;
18 };
19
6 class word { 20 class word {
7 protected: 21 protected:
8 const data* _data; 22 const data* _data;
@@ -10,6 +24,7 @@ namespace verbly {
10 bool _valid = false; 24 bool _valid = false;
11 25
12 std::list<std::list<std::string>> pronunciations; 26 std::list<std::list<std::string>> pronunciations;
27 std::list<rhyme> rhymes;
13 28
14 word(); 29 word();
15 word(const data& _data, int _id); 30 word(const data& _data, int _id);
@@ -24,7 +39,7 @@ namespace verbly {
24 public: 39 public:
25 virtual std::string base_form() const = 0; 40 virtual std::string base_form() const = 0;
26 41
27 std::list<std::string> rhyme_phonemes() const; 42 std::list<rhyme> get_rhymes() const;
28 bool starts_with_vowel_sound() const; 43 bool starts_with_vowel_sound() const;
29 }; 44 };
30 45