diff options
author | Kelly Rauchenberger <fefferburbia@gmail.com> | 2016-04-17 13:44:37 -0400 |
---|---|---|
committer | Kelly Rauchenberger <fefferburbia@gmail.com> | 2016-04-17 13:44:37 -0400 |
commit | 04338f2b040fee5142904c062e0e38c836601034 (patch) | |
tree | a3ca42f738839ae4f6c83d599277c33203beb733 | |
parent | 040ee58fecdc9c478004bc2e554e1ae126ec4602 (diff) | |
download | verbly-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.
-rw-r--r-- | generator/generator.cpp | 128 | ||||
-rw-r--r-- | generator/schema.sql | 8 | ||||
-rw-r--r-- | lib/adjective_query.cpp | 68 | ||||
-rw-r--r-- | lib/adjective_query.h | 10 | ||||
-rw-r--r-- | lib/adverb_query.cpp | 68 | ||||
-rw-r--r-- | lib/adverb_query.h | 10 | ||||
-rw-r--r-- | lib/data.cpp | 2 | ||||
-rw-r--r-- | lib/frame_query.cpp | 2 | ||||
-rw-r--r-- | lib/noun_query.cpp | 73 | ||||
-rw-r--r-- | lib/noun_query.h | 10 | ||||
-rw-r--r-- | lib/preposition.cpp | 2 | ||||
-rw-r--r-- | lib/verb_query.cpp | 68 | ||||
-rw-r--r-- | lib/verb_query.h | 10 | ||||
-rw-r--r-- | lib/word.cpp | 41 | ||||
-rw-r--r-- | lib/word.h | 17 |
15 files changed, 442 insertions, 75 deletions
diff --git a/generator/generator.cpp b/generator/generator.cpp index e67bda7..e2ebfa1 100644 --- a/generator/generator.cpp +++ b/generator/generator.cpp | |||
@@ -76,13 +76,24 @@ struct group_t { | |||
76 | std::list<std::list<framepart_t>> frames; | 76 | std::list<std::list<framepart_t>> frames; |
77 | }; | 77 | }; |
78 | 78 | ||
79 | struct pronunciation_t { | ||
80 | std::string phonemes; | ||
81 | std::string prerhyme; | ||
82 | std::string rhyme; | ||
83 | |||
84 | bool operator<(const pronunciation_t& other) const | ||
85 | { | ||
86 | return phonemes < other.phonemes; | ||
87 | } | ||
88 | }; | ||
89 | |||
79 | std::map<std::string, group_t> groups; | 90 | std::map<std::string, group_t> groups; |
80 | std::map<std::string, verb_t> verbs; | 91 | std::map<std::string, verb_t> verbs; |
81 | std::map<std::string, adjective_t> adjectives; | 92 | std::map<std::string, adjective_t> adjectives; |
82 | std::map<std::string, noun_t> nouns; | 93 | std::map<std::string, noun_t> nouns; |
83 | std::map<int, std::map<int, int>> wn; | 94 | std::map<int, std::map<int, int>> wn; |
84 | std::map<int, int> images; | 95 | std::map<int, int> images; |
85 | std::map<std::string, std::set<std::string>> pronunciations; | 96 | std::map<std::string, std::set<pronunciation_t>> pronunciations; |
86 | 97 | ||
87 | void print_usage() | 98 | void print_usage() |
88 | { | 99 | { |
@@ -590,7 +601,47 @@ int main(int argc, char** argv) | |||
590 | std::string canonical(phoneme_data[1]); | 601 | std::string canonical(phoneme_data[1]); |
591 | std::transform(std::begin(canonical), std::end(canonical), std::begin(canonical), ::tolower); | 602 | std::transform(std::begin(canonical), std::end(canonical), std::begin(canonical), ::tolower); |
592 | 603 | ||
593 | pronunciations[canonical].insert(phoneme_data[2]); | 604 | std::string phonemes = phoneme_data[2]; |
605 | auto phoneme_set = verbly::split<std::list<std::string>>(phonemes, " "); | ||
606 | auto phemstrt = std::find_if(std::begin(phoneme_set), std::end(phoneme_set), [] (std::string phoneme) { | ||
607 | return phoneme.find("1") != std::string::npos; | ||
608 | }); | ||
609 | |||
610 | pronunciation_t p; | ||
611 | p.phonemes = phonemes; | ||
612 | if (phemstrt != std::end(phoneme_set)) | ||
613 | { | ||
614 | std::stringstream rhymer; | ||
615 | for (auto it = phemstrt; it != std::end(phoneme_set); it++) | ||
616 | { | ||
617 | std::string naked; | ||
618 | std::remove_copy_if(std::begin(*it), std::end(*it), std::back_inserter(naked), [] (char ch) { | ||
619 | return isdigit(ch); | ||
620 | }); | ||
621 | |||
622 | if (it != phemstrt) | ||
623 | { | ||
624 | rhymer << " "; | ||
625 | } | ||
626 | |||
627 | rhymer << naked; | ||
628 | } | ||
629 | |||
630 | p.rhyme = rhymer.str(); | ||
631 | |||
632 | if (phemstrt != std::begin(phoneme_set)) | ||
633 | { | ||
634 | phemstrt--; | ||
635 | p.prerhyme = *phemstrt; | ||
636 | } else { | ||
637 | p.prerhyme = ""; | ||
638 | } | ||
639 | } else { | ||
640 | p.prerhyme = ""; | ||
641 | p.rhyme = ""; | ||
642 | } | ||
643 | |||
644 | pronunciations[canonical].insert(p); | ||
594 | } | 645 | } |
595 | } | 646 | } |
596 | 647 | ||
@@ -720,7 +771,7 @@ int main(int argc, char** argv) | |||
720 | db_error(ppdb, query); | 771 | db_error(ppdb, query); |
721 | } | 772 | } |
722 | 773 | ||
723 | sqlite3_bind_text(ppstmt, 1, prep.c_str(), prep.length(), SQLITE_STATIC); | 774 | sqlite3_bind_text(ppstmt, 1, prep.c_str(), prep.length(), SQLITE_TRANSIENT); |
724 | 775 | ||
725 | if (sqlite3_step(ppstmt) != SQLITE_DONE) | 776 | if (sqlite3_step(ppstmt) != SQLITE_DONE) |
726 | { | 777 | { |
@@ -752,7 +803,7 @@ int main(int argc, char** argv) | |||
752 | } | 803 | } |
753 | 804 | ||
754 | sqlite3_bind_int(ppstmt, 1, rowid); | 805 | sqlite3_bind_int(ppstmt, 1, rowid); |
755 | sqlite3_bind_text(ppstmt, 2, group.c_str(), group.length(), SQLITE_STATIC); | 806 | sqlite3_bind_text(ppstmt, 2, group.c_str(), group.length(), SQLITE_TRANSIENT); |
756 | 807 | ||
757 | if (sqlite3_step(ppstmt) != SQLITE_DONE) | 808 | if (sqlite3_step(ppstmt) != SQLITE_DONE) |
758 | { | 809 | { |
@@ -775,11 +826,11 @@ int main(int argc, char** argv) | |||
775 | db_error(ppdb, query); | 826 | db_error(ppdb, query); |
776 | } | 827 | } |
777 | 828 | ||
778 | sqlite3_bind_text(ppstmt, 1, mapping.second.infinitive.c_str(), mapping.second.infinitive.length(), SQLITE_STATIC); | 829 | sqlite3_bind_text(ppstmt, 1, mapping.second.infinitive.c_str(), mapping.second.infinitive.length(), SQLITE_TRANSIENT); |
779 | sqlite3_bind_text(ppstmt, 2, mapping.second.past_tense.c_str(), mapping.second.past_tense.length(), SQLITE_STATIC); | 830 | sqlite3_bind_text(ppstmt, 2, mapping.second.past_tense.c_str(), mapping.second.past_tense.length(), SQLITE_TRANSIENT); |
780 | sqlite3_bind_text(ppstmt, 3, mapping.second.past_participle.c_str(), mapping.second.past_participle.length(), SQLITE_STATIC); | 831 | sqlite3_bind_text(ppstmt, 3, mapping.second.past_participle.c_str(), mapping.second.past_participle.length(), SQLITE_TRANSIENT); |
781 | sqlite3_bind_text(ppstmt, 4, mapping.second.ing_form.c_str(), mapping.second.ing_form.length(), SQLITE_STATIC); | 832 | sqlite3_bind_text(ppstmt, 4, mapping.second.ing_form.c_str(), mapping.second.ing_form.length(), SQLITE_TRANSIENT); |
782 | sqlite3_bind_text(ppstmt, 5, mapping.second.s_form.c_str(), mapping.second.s_form.length(), SQLITE_STATIC); | 833 | sqlite3_bind_text(ppstmt, 5, mapping.second.s_form.c_str(), mapping.second.s_form.length(), SQLITE_TRANSIENT); |
783 | 834 | ||
784 | if (sqlite3_step(ppstmt) != SQLITE_DONE) | 835 | if (sqlite3_step(ppstmt) != SQLITE_DONE) |
785 | { | 836 | { |
@@ -811,14 +862,26 @@ int main(int argc, char** argv) | |||
811 | 862 | ||
812 | for (auto pronunciation : pronunciations[canonical]) | 863 | for (auto pronunciation : pronunciations[canonical]) |
813 | { | 864 | { |
814 | query = "INSERT INTO verb_pronunciations (verb_id, pronunciation) VALUES (?, ?)"; | 865 | if (!pronunciation.rhyme.empty()) |
866 | { | ||
867 | query = "INSERT INTO verb_pronunciations (verb_id, pronunciation, prerhyme, rhyme) VALUES (?, ?, ?, ?)"; | ||
868 | } else { | ||
869 | query = "INSERT INTO verb_pronunciations (verb_id, pronunciation) VALUES (?, ?)"; | ||
870 | } | ||
871 | |||
815 | if (sqlite3_prepare_v2(ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) | 872 | if (sqlite3_prepare_v2(ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) |
816 | { | 873 | { |
817 | db_error(ppdb, query); | 874 | db_error(ppdb, query); |
818 | } | 875 | } |
819 | 876 | ||
820 | sqlite3_bind_int(ppstmt, 1, rowid); | 877 | sqlite3_bind_int(ppstmt, 1, rowid); |
821 | sqlite3_bind_text(ppstmt, 2, pronunciation.c_str(), pronunciation.length(), SQLITE_STATIC); | 878 | sqlite3_bind_text(ppstmt, 2, pronunciation.phonemes.c_str(), pronunciation.phonemes.length(), SQLITE_TRANSIENT); |
879 | |||
880 | if (!pronunciation.rhyme.empty()) | ||
881 | { | ||
882 | sqlite3_bind_text(ppstmt, 3, pronunciation.prerhyme.c_str(), pronunciation.prerhyme.length(), SQLITE_TRANSIENT); | ||
883 | sqlite3_bind_text(ppstmt, 4, pronunciation.rhyme.c_str(), pronunciation.rhyme.length(), SQLITE_TRANSIENT); | ||
884 | } | ||
822 | 885 | ||
823 | if (sqlite3_step(ppstmt) != SQLITE_DONE) | 886 | if (sqlite3_step(ppstmt) != SQLITE_DONE) |
824 | { | 887 | { |
@@ -856,7 +919,7 @@ int main(int argc, char** argv) | |||
856 | db_error(ppdb, query); | 919 | db_error(ppdb, query); |
857 | } | 920 | } |
858 | 921 | ||
859 | sqlite3_bind_blob(ppstmt, 1, rdm.c_str(), rdm.size(), SQLITE_STATIC); | 922 | sqlite3_bind_blob(ppstmt, 1, rdm.c_str(), rdm.size(), SQLITE_TRANSIENT); |
860 | 923 | ||
861 | if (sqlite3_step(ppstmt) != SQLITE_DONE) | 924 | if (sqlite3_step(ppstmt) != SQLITE_DONE) |
862 | { | 925 | { |
@@ -949,7 +1012,7 @@ int main(int argc, char** argv) | |||
949 | } | 1012 | } |
950 | 1013 | ||
951 | sqlite3_bind_int(ppstmt, 1, gid); | 1014 | sqlite3_bind_int(ppstmt, 1, gid); |
952 | sqlite3_bind_blob(ppstmt, 2, marshall.c_str(), marshall.length(), SQLITE_STATIC); | 1015 | sqlite3_bind_blob(ppstmt, 2, marshall.c_str(), marshall.length(), SQLITE_TRANSIENT); |
953 | 1016 | ||
954 | if (sqlite3_step(ppstmt) != SQLITE_DONE) | 1017 | if (sqlite3_step(ppstmt) != SQLITE_DONE) |
955 | { | 1018 | { |
@@ -1104,7 +1167,7 @@ int main(int argc, char** argv) | |||
1104 | db_error(ppdb, query); | 1167 | db_error(ppdb, query); |
1105 | } | 1168 | } |
1106 | 1169 | ||
1107 | sqlite3_bind_text(ppstmt, 1, word.c_str(), word.length(), SQLITE_STATIC); | 1170 | sqlite3_bind_text(ppstmt, 1, word.c_str(), word.length(), SQLITE_TRANSIENT); |
1108 | switch (synset_id / 100000000) | 1171 | switch (synset_id / 100000000) |
1109 | { | 1172 | { |
1110 | case 1: // Noun | 1173 | case 1: // Noun |
@@ -1119,7 +1182,7 @@ int main(int argc, char** argv) | |||
1119 | 1182 | ||
1120 | if (nouns.count(word) == 1) | 1183 | if (nouns.count(word) == 1) |
1121 | { | 1184 | { |
1122 | sqlite3_bind_text(ppstmt, 6, nouns[word].plural.c_str(), nouns[word].plural.length(), SQLITE_STATIC); | 1185 | sqlite3_bind_text(ppstmt, 6, nouns[word].plural.c_str(), nouns[word].plural.length(), SQLITE_TRANSIENT); |
1123 | } | 1186 | } |
1124 | 1187 | ||
1125 | break; | 1188 | break; |
@@ -1132,8 +1195,8 @@ int main(int argc, char** argv) | |||
1132 | 1195 | ||
1133 | if (adjectives.count(word) == 1) | 1196 | if (adjectives.count(word) == 1) |
1134 | { | 1197 | { |
1135 | sqlite3_bind_text(ppstmt, 3, adjectives[word].comparative.c_str(), adjectives[word].comparative.length(), SQLITE_STATIC); | 1198 | sqlite3_bind_text(ppstmt, 3, adjectives[word].comparative.c_str(), adjectives[word].comparative.length(), SQLITE_TRANSIENT); |
1136 | sqlite3_bind_text(ppstmt, 4, adjectives[word].superlative.c_str(), adjectives[word].superlative.length(), SQLITE_STATIC); | 1199 | sqlite3_bind_text(ppstmt, 4, adjectives[word].superlative.c_str(), adjectives[word].superlative.length(), SQLITE_TRANSIENT); |
1137 | } | 1200 | } |
1138 | 1201 | ||
1139 | break; | 1202 | break; |
@@ -1173,21 +1236,36 @@ int main(int argc, char** argv) | |||
1173 | { | 1236 | { |
1174 | case 1: // Noun | 1237 | case 1: // Noun |
1175 | { | 1238 | { |
1176 | query = "INSERT INTO noun_pronunciations (noun_id, pronunciation) VALUES (?, ?)"; | 1239 | if (!pronunciation.rhyme.empty()) |
1240 | { | ||
1241 | query = "INSERT INTO noun_pronunciations (noun_id, pronunciation, prerhyme, rhyme) VALUES (?, ?, ?, ?)"; | ||
1242 | } else { | ||
1243 | query = "INSERT INTO noun_pronunciations (noun_id, pronunciation) VALUES (?, ?)"; | ||
1244 | } | ||
1177 | 1245 | ||
1178 | break; | 1246 | break; |
1179 | } | 1247 | } |
1180 | 1248 | ||
1181 | case 3: // Adjective | 1249 | case 3: // Adjective |
1182 | { | 1250 | { |
1183 | query = "INSERT INTO adjective_pronunciations (adjective_id, pronunciation) VALUES (?, ?)"; | 1251 | if (!pronunciation.rhyme.empty()) |
1252 | { | ||
1253 | query = "INSERT INTO adjective_pronunciations (adjective_id, pronunciation, prerhyme, rhyme) VALUES (?, ?, ?, ?)"; | ||
1254 | } else { | ||
1255 | query = "INSERT INTO adjective_pronunciations (adjective_id, pronunciation) VALUES (?, ?)"; | ||
1256 | } | ||
1184 | 1257 | ||
1185 | break; | 1258 | break; |
1186 | } | 1259 | } |
1187 | 1260 | ||
1188 | case 4: // Adverb | 1261 | case 4: // Adverb |
1189 | { | 1262 | { |
1190 | query = "INSERT INTO adverb_pronunciations (adverb_id, pronunciation) VALUES (?, ?)"; | 1263 | if (!pronunciation.rhyme.empty()) |
1264 | { | ||
1265 | query = "INSERT INTO adverb_pronunciations (adverb_id, pronunciation, prerhyme, rhyme) VALUES (?, ?, ?, ?)"; | ||
1266 | } else { | ||
1267 | query = "INSERT INTO adverb_pronunciations (adverb_id, pronunciation) VALUES (?, ?)"; | ||
1268 | } | ||
1191 | 1269 | ||
1192 | break; | 1270 | break; |
1193 | } | 1271 | } |
@@ -1199,7 +1277,13 @@ int main(int argc, char** argv) | |||
1199 | } | 1277 | } |
1200 | 1278 | ||
1201 | sqlite3_bind_int(ppstmt, 1, rowid); | 1279 | sqlite3_bind_int(ppstmt, 1, rowid); |
1202 | sqlite3_bind_text(ppstmt, 2, pronunciation.c_str(), pronunciation.length(), SQLITE_STATIC); | 1280 | sqlite3_bind_text(ppstmt, 2, pronunciation.phonemes.c_str(), pronunciation.phonemes.length(), SQLITE_TRANSIENT); |
1281 | |||
1282 | if (!pronunciation.rhyme.empty()) | ||
1283 | { | ||
1284 | sqlite3_bind_text(ppstmt, 3, pronunciation.prerhyme.c_str(), pronunciation.prerhyme.length(), SQLITE_TRANSIENT); | ||
1285 | sqlite3_bind_text(ppstmt, 4, pronunciation.rhyme.c_str(), pronunciation.rhyme.length(), SQLITE_TRANSIENT); | ||
1286 | } | ||
1203 | 1287 | ||
1204 | if (sqlite3_step(ppstmt) != SQLITE_DONE) | 1288 | if (sqlite3_step(ppstmt) != SQLITE_DONE) |
1205 | { | 1289 | { |
@@ -2188,7 +2272,7 @@ int main(int argc, char** argv) | |||
2188 | db_error(ppdb, query); | 2272 | db_error(ppdb, query); |
2189 | } | 2273 | } |
2190 | 2274 | ||
2191 | sqlite3_bind_text(ppstmt, 1, syn.c_str(), 1, SQLITE_STATIC); | 2275 | sqlite3_bind_text(ppstmt, 1, syn.c_str(), 1, SQLITE_TRANSIENT); |
2192 | sqlite3_bind_int(ppstmt, 2, wn[synset_id][wnum]); | 2276 | sqlite3_bind_int(ppstmt, 2, wn[synset_id][wnum]); |
2193 | 2277 | ||
2194 | if (sqlite3_step(ppstmt) != SQLITE_DONE) | 2278 | if (sqlite3_step(ppstmt) != SQLITE_DONE) |
diff --git a/generator/schema.sql b/generator/schema.sql index 9a39944..1836c62 100644 --- a/generator/schema.sql +++ b/generator/schema.sql | |||
@@ -184,6 +184,8 @@ DROP TABLE IF EXISTS `noun_pronunciations`; | |||
184 | CREATE TABLE `noun_pronunciations` ( | 184 | CREATE TABLE `noun_pronunciations` ( |
185 | `noun_id` INTEGER NOT NULL, | 185 | `noun_id` INTEGER NOT NULL, |
186 | `pronunciation` VARCHAR(64) NOT NULL, | 186 | `pronunciation` VARCHAR(64) NOT NULL, |
187 | `prerhyme` VARCHAR(8), | ||
188 | `rhyme` VARCHAR(64), | ||
187 | FOREIGN KEY (`noun_id`) REFERENCES `nouns`(`noun_id`) | 189 | FOREIGN KEY (`noun_id`) REFERENCES `nouns`(`noun_id`) |
188 | ); | 190 | ); |
189 | 191 | ||
@@ -191,6 +193,8 @@ DROP TABLE IF EXISTS `verb_pronunciations`; | |||
191 | CREATE TABLE `verb_pronunciations` ( | 193 | CREATE TABLE `verb_pronunciations` ( |
192 | `verb_id` INTEGER NOT NULL, | 194 | `verb_id` INTEGER NOT NULL, |
193 | `pronunciation` VARCHAR(64) NOT NULL, | 195 | `pronunciation` VARCHAR(64) NOT NULL, |
196 | `prerhyme` VARCHAR(8), | ||
197 | `rhyme` VARCHAR(64), | ||
194 | FOREIGN KEY (`verb_id`) REFERENCES `verbs`(`verb_id`) | 198 | FOREIGN KEY (`verb_id`) REFERENCES `verbs`(`verb_id`) |
195 | ); | 199 | ); |
196 | 200 | ||
@@ -198,6 +202,8 @@ DROP TABLE IF EXISTS `adjective_pronunciations`; | |||
198 | CREATE TABLE `adjective_pronunciations` ( | 202 | CREATE TABLE `adjective_pronunciations` ( |
199 | `adjective_id` INTEGER NOT NULL, | 203 | `adjective_id` INTEGER NOT NULL, |
200 | `pronunciation` VARCHAR(64) NOT NULL, | 204 | `pronunciation` VARCHAR(64) NOT NULL, |
205 | `prerhyme` VARCHAR(8), | ||
206 | `rhyme` VARCHAR(64), | ||
201 | FOREIGN KEY (`adjective_id`) REFERENCES `adjectives`(`adjective_id`) | 207 | FOREIGN KEY (`adjective_id`) REFERENCES `adjectives`(`adjective_id`) |
202 | ); | 208 | ); |
203 | 209 | ||
@@ -205,6 +211,8 @@ DROP TABLE IF EXISTS `adverb_pronunciations`; | |||
205 | CREATE TABLE `adverb_pronunciations` ( | 211 | CREATE TABLE `adverb_pronunciations` ( |
206 | `adverb_id` INTEGER NOT NULL, | 212 | `adverb_id` INTEGER NOT NULL, |
207 | `pronunciation` VARCHAR(64) NOT NULL, | 213 | `pronunciation` VARCHAR(64) NOT NULL, |
214 | `prerhyme` VARCHAR(8), | ||
215 | `rhyme` VARCHAR(64), | ||
208 | FOREIGN KEY (`adverb_id`) REFERENCES `adverbs`(`adverb_id`) | 216 | FOREIGN KEY (`adverb_id`) REFERENCES `adverbs`(`adverb_id`) |
209 | ); | 217 | ); |
210 | 218 | ||
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 | ||
3 | namespace verbly { | 3 | namespace 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 | ||
4 | namespace verbly { | 4 | namespace 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 | ||
4 | namespace verbly { | 4 | namespace 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 | ||