poefy 0.6.1 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +3 -0
- data/.rspec +0 -1
- data/README.md +185 -37
- data/bin/poefy +88 -56
- data/bin/poefy_make +93 -0
- data/lib/poefy/conditional_sample.rb +85 -0
- data/lib/poefy/core_extensions/array.rb +78 -39
- data/lib/poefy/database.rb +53 -176
- data/lib/poefy/db_type.rb +64 -0
- data/lib/poefy/generation.rb +5 -27
- data/lib/poefy/handle_error.rb +9 -1
- data/lib/poefy/{poefy_gen_base.rb → poem_base.rb} +17 -37
- data/lib/poefy/poetic_form_from_text.rb +1 -1
- data/lib/poefy/poetic_forms.rb +0 -1
- data/lib/poefy/self.rb +39 -21
- data/lib/poefy/string_manipulation.rb +1 -1
- data/lib/poefy/version.rb +26 -29
- data/lib/poefy.rb +10 -15
- data/poefy.gemspec +16 -5
- data/spec/poefy_unit_spec.rb +199 -0
- data/spec/spec_helper.rb +2 -0
- metadata +53 -14
- data/data/spec_test_tiny.txt +0 -12
- data/lib/poefy/conditional_satisfaction.rb +0 -226
- data/spec/poefy_spec.rb +0 -722
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: poefy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Paul Thompson
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-10-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -53,25 +53,53 @@ dependencies:
|
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '3.0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name: sqlite3
|
56
|
+
name: poefy-sqlite3
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
59
|
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '1
|
61
|
+
version: '0.1'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0.1'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: poefy-pg
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0.1'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0.1'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: conditional_sample
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '1.0'
|
62
90
|
- - ">="
|
63
91
|
- !ruby/object:Gem::Version
|
64
|
-
version: 1.
|
92
|
+
version: 1.0.0
|
65
93
|
type: :runtime
|
66
94
|
prerelease: false
|
67
95
|
version_requirements: !ruby/object:Gem::Requirement
|
68
96
|
requirements:
|
69
97
|
- - "~>"
|
70
98
|
- !ruby/object:Gem::Version
|
71
|
-
version: '1.
|
99
|
+
version: '1.0'
|
72
100
|
- - ">="
|
73
101
|
- !ruby/object:Gem::Version
|
74
|
-
version: 1.
|
102
|
+
version: 1.0.0
|
75
103
|
- !ruby/object:Gem::Dependency
|
76
104
|
name: ruby_rhymes
|
77
105
|
requirement: !ruby/object:Gem::Requirement
|
@@ -133,12 +161,14 @@ dependencies:
|
|
133
161
|
- !ruby/object:Gem::Version
|
134
162
|
version: 1.4.0
|
135
163
|
description: Create poems from an input text file, by generating and querying a SQLite
|
136
|
-
database describing each line. Poems are created using a template
|
137
|
-
from the database, according to closing rhyme, syllable count, and
|
164
|
+
or PostgreSQL database describing each line. Poems are created using a template
|
165
|
+
to select lines from the database, according to closing rhyme, syllable count, and
|
166
|
+
regex matching.
|
138
167
|
email:
|
139
168
|
- nossidge@gmail.com
|
140
169
|
executables:
|
141
170
|
- poefy
|
171
|
+
- poefy_make
|
142
172
|
extensions: []
|
143
173
|
extra_rdoc_files: []
|
144
174
|
files:
|
@@ -149,32 +179,41 @@ files:
|
|
149
179
|
- README.md
|
150
180
|
- Rakefile
|
151
181
|
- bin/poefy
|
182
|
+
- bin/poefy_make
|
152
183
|
- data/emily_dickinson.txt
|
153
184
|
- data/english_as_she_is_spoke.txt
|
154
185
|
- data/shakespeare_sonnets.txt
|
155
|
-
- data/spec_test_tiny.txt
|
156
186
|
- data/st_therese_of_lisieux.txt
|
157
187
|
- data/whitman_leaves.txt
|
158
188
|
- lib/poefy.rb
|
159
|
-
- lib/poefy/
|
189
|
+
- lib/poefy/conditional_sample.rb
|
160
190
|
- lib/poefy/core_extensions/array.rb
|
161
191
|
- lib/poefy/database.rb
|
192
|
+
- lib/poefy/db_type.rb
|
162
193
|
- lib/poefy/generation.rb
|
163
194
|
- lib/poefy/handle_error.rb
|
164
|
-
- lib/poefy/
|
195
|
+
- lib/poefy/poem_base.rb
|
165
196
|
- lib/poefy/poetic_form_from_text.rb
|
166
197
|
- lib/poefy/poetic_forms.rb
|
167
198
|
- lib/poefy/self.rb
|
168
199
|
- lib/poefy/string_manipulation.rb
|
169
200
|
- lib/poefy/version.rb
|
170
201
|
- poefy.gemspec
|
171
|
-
- spec/
|
202
|
+
- spec/poefy_unit_spec.rb
|
172
203
|
- spec/spec_helper.rb
|
173
204
|
homepage: https://github.com/nossidge/poefy
|
174
205
|
licenses:
|
175
206
|
- GPL-3.0
|
176
207
|
metadata: {}
|
177
|
-
post_install_message:
|
208
|
+
post_install_message: |-
|
209
|
+
---
|
210
|
+
Thanks for installing poefy.
|
211
|
+
Please also install one of the below gems:
|
212
|
+
$ gem install poefy-pg
|
213
|
+
$ gem install poefy-sqlite
|
214
|
+
Then run this command to generate the included corpora:
|
215
|
+
$ poefy_make
|
216
|
+
---
|
178
217
|
rdoc_options: []
|
179
218
|
require_paths:
|
180
219
|
- lib
|
data/data/spec_test_tiny.txt
DELETED
@@ -1,226 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
# Encoding: UTF-8
|
3
|
-
|
4
|
-
################################################################################
|
5
|
-
# Two methods for assessing permutations of an input array versus an
|
6
|
-
# array of conditions for each element.
|
7
|
-
# Both methods return an output array consisting of samples from an
|
8
|
-
# input array, for which output[0] satisfies condition[0], etc.
|
9
|
-
# Both methods may take a whole lot of time, depending on how lenient the
|
10
|
-
# conditions are. It is better for the stricter conditions to be at the
|
11
|
-
# start of the array, due to the way the code is written.
|
12
|
-
# If none of the conditions match, then it will run in factorial time,
|
13
|
-
# which will get exponentially longer the more elements there are in the
|
14
|
-
# input array.
|
15
|
-
# I would recommend wrapping inside a Timeout block to assuage this. If it
|
16
|
-
# fails to resolve in, say, two seconds, then it's probably not possible
|
17
|
-
# to fit the conditions to the lines:
|
18
|
-
# begin
|
19
|
-
# Timeout::timeout(2) do
|
20
|
-
# output = conditional_selection(lines.shuffle, conditions)
|
21
|
-
# end
|
22
|
-
# rescue
|
23
|
-
# output = []
|
24
|
-
# end
|
25
|
-
################################################################################
|
26
|
-
# '#conditional_permutation' returns a complete permutation of an array.
|
27
|
-
# i.e. output length == array length
|
28
|
-
# Any elements in the array that are extra to the number of conditions will
|
29
|
-
# be assumed valid.
|
30
|
-
# array = [1,2,3,4,5].shuffle
|
31
|
-
# conditions = [
|
32
|
-
# proc { |arr, elem| elem < 2},
|
33
|
-
# proc { |arr, elem| elem > 2},
|
34
|
-
# proc { |arr, elem| elem > 1}
|
35
|
-
# ]
|
36
|
-
# possible output = [1,3,4,5,2]
|
37
|
-
################################################################################
|
38
|
-
# '#conditional_selection' returns an array that satisfies only the conditions.
|
39
|
-
# i.e. output length == conditions length
|
40
|
-
# array = [1,2,3,4,5].shuffle
|
41
|
-
# conditions = [
|
42
|
-
# proc { |arr, elem| elem < 2},
|
43
|
-
# proc { |arr, elem| elem > 2},
|
44
|
-
# proc { |arr, elem| elem > 1}
|
45
|
-
# ]
|
46
|
-
# possible output = [1,5,3]
|
47
|
-
################################################################################
|
48
|
-
# Condition array:
|
49
|
-
# Must contain boolean procs using args |arr, elem|
|
50
|
-
# 'arr' is a reference to the current array that has been built up
|
51
|
-
# through the recursion chain.
|
52
|
-
# 'elem' is a reference to the current element.
|
53
|
-
################################################################################
|
54
|
-
|
55
|
-
module Poefy
|
56
|
-
|
57
|
-
module ConditionalSatisfaction
|
58
|
-
|
59
|
-
# Delete the first matching value in an array.
|
60
|
-
def delete_first array, value
|
61
|
-
array.delete_at(array.index(value) || array.length)
|
62
|
-
end
|
63
|
-
|
64
|
-
# Make sure each line ends with a different word.
|
65
|
-
# This is intented to be used in 'conditions' procs.
|
66
|
-
def diff_end arr, elem
|
67
|
-
!arr.map{ |i| i['final_word'] }.include?(elem['final_word'])
|
68
|
-
end
|
69
|
-
|
70
|
-
# See if a line matches to a particular 'poetic_form'
|
71
|
-
def validate_line line, poetic_form
|
72
|
-
valid = true
|
73
|
-
if poetic_form[:syllable] and poetic_form[:syllable] != 0
|
74
|
-
valid = valid && [*poetic_form[:syllable]].include?(line['syllables'])
|
75
|
-
end
|
76
|
-
if poetic_form[:regex]
|
77
|
-
[*poetic_form[:regex]].each do |i|
|
78
|
-
valid = valid && !!(line['line'].match(i))
|
79
|
-
end
|
80
|
-
end
|
81
|
-
valid
|
82
|
-
end
|
83
|
-
|
84
|
-
# Input a rhyme array and a poetic_form hash.
|
85
|
-
# Create a line by line array of conditions.
|
86
|
-
# This will be used to analyse the validity of corpus lines.
|
87
|
-
def conditions_by_line tokenised_rhyme, poetic_form
|
88
|
-
output = []
|
89
|
-
tokenised_rhyme.each.with_index do |rhyme, index|
|
90
|
-
line_hash = {
|
91
|
-
line: index + 1,
|
92
|
-
rhyme: rhyme[:token],
|
93
|
-
rhyme_letter: rhyme[:rhyme_letter]
|
94
|
-
}
|
95
|
-
if rhyme[:refrain] and rhyme[:refrain] != ' '
|
96
|
-
line_hash[:refrain] = rhyme[:refrain]
|
97
|
-
end
|
98
|
-
line_hash[:exact] = rhyme[:exact] if rhyme[:exact]
|
99
|
-
poetic_form.keys.each do |k|
|
100
|
-
if poetic_form[k].is_a? Hash
|
101
|
-
line_hash[k] = poetic_form[k][index + 1]
|
102
|
-
end
|
103
|
-
end
|
104
|
-
output << line_hash
|
105
|
-
end
|
106
|
-
output
|
107
|
-
end
|
108
|
-
|
109
|
-
# Group by element, with count as value. Ignore spaces.
|
110
|
-
# e.g. {"A1"=>4, "b"=>6, "A2"=>4, "a"=>5}
|
111
|
-
# => {"b"=>6, "a"=>7}
|
112
|
-
def unique_rhymes tokenised_rhyme
|
113
|
-
|
114
|
-
# Group by element, with count as value. Ignore spaces.
|
115
|
-
# e.g. {"A1"=>4, "b"=>6, "A2"=>4, "a"=>5}
|
116
|
-
tokens = tokenised_rhyme.reject { |i| i == ' ' }
|
117
|
-
grouped = tokens.each_with_object(Hash.new(0)) { |k,h| h[k] += 1 }
|
118
|
-
|
119
|
-
# For each uppercase token, add one to the corresponding lowercase.
|
120
|
-
uppers = grouped.keys.select{ |i| /[[:upper:]]/.match(i) }
|
121
|
-
uppers.each { |i| grouped[i[0].downcase] += 1 }
|
122
|
-
|
123
|
-
# Delete from the grouped hash if uppercase.
|
124
|
-
grouped.delete_if { |k,v| /[[:upper:]]/.match(k) }
|
125
|
-
grouped
|
126
|
-
end
|
127
|
-
|
128
|
-
############################################################################
|
129
|
-
|
130
|
-
# Return a permutation of 'array' where each element validates to the
|
131
|
-
# same index in a 'conditions' array of procs that return Boolean.
|
132
|
-
# Will not work on arrays that contain nil values.
|
133
|
-
def conditional_permutation array, conditions,
|
134
|
-
current_iter = 0,
|
135
|
-
current_array = []
|
136
|
-
output = []
|
137
|
-
|
138
|
-
# Get the current conditional.
|
139
|
-
cond = conditions[current_iter]
|
140
|
-
|
141
|
-
# Loop through and return the first element that validates.
|
142
|
-
valid = false
|
143
|
-
array.each do |elem|
|
144
|
-
|
145
|
-
# Test the condition. If we've run out of elements
|
146
|
-
# in the condition array, then allow any value.
|
147
|
-
valid = cond ? cond.call(current_array, elem) : true
|
148
|
-
if valid
|
149
|
-
|
150
|
-
# Remove this element from the array, and recurse.
|
151
|
-
remain = array.dup
|
152
|
-
delete_first(remain, elem)
|
153
|
-
|
154
|
-
# If the remaining array is empty, no need to recurse.
|
155
|
-
new_val = nil
|
156
|
-
if !remain.empty?
|
157
|
-
new_val = conditional_permutation(remain, conditions,
|
158
|
-
current_iter + 1,
|
159
|
-
current_array + [elem])
|
160
|
-
end
|
161
|
-
|
162
|
-
# If we cannot use this value, because it breaks future conditions.
|
163
|
-
if !remain.empty? && new_val.empty?
|
164
|
-
valid = false
|
165
|
-
else
|
166
|
-
output << elem << new_val
|
167
|
-
end
|
168
|
-
end
|
169
|
-
|
170
|
-
break if valid
|
171
|
-
end
|
172
|
-
|
173
|
-
output.flatten.compact
|
174
|
-
end
|
175
|
-
|
176
|
-
# Return values from 'array' where each element validates to the same
|
177
|
-
# index in a 'conditions' array of procs that return Boolean.
|
178
|
-
# Return an array of conditions.length
|
179
|
-
def conditional_selection array, conditions,
|
180
|
-
current_iter = 0,
|
181
|
-
current_array = []
|
182
|
-
output = []
|
183
|
-
|
184
|
-
# Get the current conditional.
|
185
|
-
cond = conditions[current_iter]
|
186
|
-
|
187
|
-
# Return nil if we have reached the end of the conditionals.
|
188
|
-
return nil if cond.nil?
|
189
|
-
|
190
|
-
# Loop through and return the first element that validates.
|
191
|
-
valid = false
|
192
|
-
array.each do |elem|
|
193
|
-
|
194
|
-
# Test the condition. If we've run out of elements
|
195
|
-
# in the condition array, then allow any value.
|
196
|
-
valid = cond.call(current_array, elem)
|
197
|
-
if valid
|
198
|
-
|
199
|
-
# Remove this element from the array, and recurse.
|
200
|
-
remain = array.dup
|
201
|
-
delete_first(remain, elem)
|
202
|
-
|
203
|
-
# If the remaining array is empty, no need to recurse.
|
204
|
-
new_val = conditional_selection(remain, conditions,
|
205
|
-
current_iter + 1,
|
206
|
-
current_array + [elem])
|
207
|
-
|
208
|
-
# If we cannot use this value, because it breaks future conditions.
|
209
|
-
if new_val and new_val.empty?
|
210
|
-
valid = false
|
211
|
-
else
|
212
|
-
output << elem << new_val
|
213
|
-
end
|
214
|
-
end
|
215
|
-
|
216
|
-
break if valid
|
217
|
-
end
|
218
|
-
|
219
|
-
output.flatten.compact
|
220
|
-
end
|
221
|
-
|
222
|
-
end
|
223
|
-
|
224
|
-
end
|
225
|
-
|
226
|
-
################################################################################
|