haiku_gadget 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +19 -0
- data/.rspec +3 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +61 -0
- data/Rakefile +1 -0
- data/haiku_gadget.gemspec +24 -0
- data/lib/assets/.keep +0 -0
- data/lib/haiku_gadget.rb +2 -0
- data/lib/haiku_gadget/dictionary.rb +147 -0
- data/lib/haiku_gadget/haiku_gadget.rb +54 -0
- data/lib/haiku_gadget/haiku_template.rb +228 -0
- data/lib/haiku_gadget/version.rb +5 -0
- data/lib/haiku_gadget/word_template.rb +44 -0
- data/lib/haiku_gadget/word_type.rb +55 -0
- data/lib/tasks/.keep +0 -0
- data/lib/words.yml +106 -0
- data/spec/haiku_gadget/haiku_gadget_spec.rb +152 -0
- data/spec/rails_helper.rb +50 -0
- data/spec/spec_helper.rb +87 -0
- data/spec/test_words_nested.yml +14 -0
- data/spec/test_words_single.yml +23 -0
- metadata +113 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 75568a716d660a54f00260d61cd5b3bc14ba0f6b
|
4
|
+
data.tar.gz: e2d7daf568e3bd89a06d0eccb7c8645d5cd0c72f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 8cb8195d7034a929b025f3dbb3c6b5e9345129d925173202ff4e00267b6afc4b4509a1a344851fe824219822e96fd46d95d7bfd2a4d0344dbd80341cb6c4ede6
|
7
|
+
data.tar.gz: 07af0a0277613866bfacee4479f5c4775632ce4e8825d23c8e2ac0959a96de4776609dc61c6418b1cc146ff6476fca0e3021c71709e0e535c7fff40438df0313
|
data/.gitignore
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
# See https://help.github.com/articles/ignoring-files for more about ignoring files.
|
2
|
+
#
|
3
|
+
# If you find yourself ignoring temporary files generated by your text editor
|
4
|
+
# or operating system, you probably want to add a global ignore instead:
|
5
|
+
# git config --global core.excludesfile '~/.gitignore_global'
|
6
|
+
|
7
|
+
# Ignore bundler config.
|
8
|
+
/.bundle
|
9
|
+
|
10
|
+
# Ignore the default SQLite database.
|
11
|
+
/db/*.sqlite3
|
12
|
+
/db/*.sqlite3-journal
|
13
|
+
|
14
|
+
# Ignore all logfiles and tempfiles.
|
15
|
+
/log/*.log
|
16
|
+
/tmp
|
17
|
+
|
18
|
+
Gemfile.lock
|
19
|
+
*.gem
|
data/.rspec
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Scott Balay
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
# Haiku Gadget
|
2
|
+
|
3
|
+
Generate random haikus!
|
4
|
+
|
5
|
+
Uses an algorithm, a custom dictionary, some grammar rules, and a team of hamsters running in wheels.
|
6
|
+
|
7
|
+
## What is a haiku?
|
8
|
+
|
9
|
+
A short poem consisting of three lines:
|
10
|
+
|
11
|
+
five syllables here
|
12
|
+
then seven syllables here
|
13
|
+
then five syllables
|
14
|
+
|
15
|
+
## Installation
|
16
|
+
|
17
|
+
Add this line to your application's Gemfile:
|
18
|
+
|
19
|
+
gem 'haiku_gadget'
|
20
|
+
|
21
|
+
And then execute:
|
22
|
+
|
23
|
+
$ bundle
|
24
|
+
|
25
|
+
Or install it yourself as:
|
26
|
+
|
27
|
+
$ gem install haiku_gadget
|
28
|
+
|
29
|
+
## Usage
|
30
|
+
|
31
|
+
First, turn on the gadget:
|
32
|
+
|
33
|
+
require 'haiku_gadget'
|
34
|
+
|
35
|
+
Get a random haiku as an array of three lines:
|
36
|
+
|
37
|
+
HaikuGadget.haiku
|
38
|
+
|
39
|
+
Or pass in a delimiter, which will return the haiku as a single string:
|
40
|
+
|
41
|
+
HaikuGadget.haiku ' / '
|
42
|
+
|
43
|
+
To get a single random line, try one of these methods:
|
44
|
+
|
45
|
+
HaikuGadget.top_line
|
46
|
+
HaikuGadget.middle_line
|
47
|
+
HaikuGadget.bottom_line
|
48
|
+
|
49
|
+
Or specify the line you want by an index:
|
50
|
+
|
51
|
+
HaikuGadget.random_line 0
|
52
|
+
HaikuGadget.random_line 1
|
53
|
+
HaikuGadget.random_line 2
|
54
|
+
|
55
|
+
## Contributing
|
56
|
+
|
57
|
+
1. Fork it ( http://github.com/zenblender/haiku_gadget/fork )
|
58
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
59
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
60
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
61
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'haiku_gadget/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "haiku_gadget"
|
8
|
+
spec.version = HaikuGadget::VERSION
|
9
|
+
spec.authors = ["Scott Balay"]
|
10
|
+
spec.email = ["sbalay@gmail.com"]
|
11
|
+
spec.summary = %q{Random haiku generator}
|
12
|
+
spec.description = %q{i know you want it / random poetic nonsense / just click a button}
|
13
|
+
spec.homepage = "http://github.com/zenblender/haiku_gadget"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.5"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
spec.add_development_dependency "rspec" , "~> 3.1"
|
24
|
+
end
|
data/lib/assets/.keep
ADDED
File without changes
|
data/lib/haiku_gadget.rb
ADDED
@@ -0,0 +1,147 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
require File.expand_path('word_type.rb', File.dirname(__FILE__))
|
4
|
+
|
5
|
+
module HaikuGadget
|
6
|
+
|
7
|
+
module Dictionary
|
8
|
+
|
9
|
+
DEFAULT_DICT_PATH = '../words.yml'
|
10
|
+
|
11
|
+
WORD_TYPES = {
|
12
|
+
determiner: WordType.new(:determiner, true),
|
13
|
+
to_be: WordType.new(:to_be, true),
|
14
|
+
adjective: WordType.new(:adjective, true),
|
15
|
+
noun: WordType.new(:noun, true, :plural),
|
16
|
+
mass_noun: WordType.new(:mass_noun),
|
17
|
+
mass_noun_determiner: WordType.new(:mass_noun_determiner),
|
18
|
+
verb: WordType.new(:verb, true, :singular),
|
19
|
+
verb_self: WordType.new(:verb_self, true, :singular),
|
20
|
+
adverb: WordType.new(:adverb),
|
21
|
+
transition_join: WordType.new(:transition_join)
|
22
|
+
}
|
23
|
+
|
24
|
+
def self.suffixed_symbol(base_symbol, suffix_symbol)
|
25
|
+
"#{base_symbol.to_s}_#{suffix_symbol.to_s}".to_sym
|
26
|
+
end
|
27
|
+
|
28
|
+
# copies words from _common into _singular and _plural
|
29
|
+
# modifies dict structure in place, doesn't return anything of consequence
|
30
|
+
def self.complete_plurality(dict, word_type)
|
31
|
+
|
32
|
+
# words that have no plurality considerations don't need to do anything here
|
33
|
+
return unless word_type.can_be_plural
|
34
|
+
|
35
|
+
base_symbol = word_type.base_symbol
|
36
|
+
|
37
|
+
common_symbol = Dictionary.suffixed_symbol base_symbol, :common
|
38
|
+
|
39
|
+
plural_symbols = [:singular, :plural]
|
40
|
+
symbols = [
|
41
|
+
Dictionary.suffixed_symbol(base_symbol, :singular),
|
42
|
+
Dictionary.suffixed_symbol(base_symbol, :plural)
|
43
|
+
]
|
44
|
+
|
45
|
+
# make sure there is a common list structure
|
46
|
+
dict[common_symbol] ||= []
|
47
|
+
|
48
|
+
# make sure there are singular/plural word list structures
|
49
|
+
symbols.each do |symbol|
|
50
|
+
dict[symbol] ||= []
|
51
|
+
end
|
52
|
+
|
53
|
+
plural_symbols.each do |plural_symbol|
|
54
|
+
|
55
|
+
symbol = Dictionary.suffixed_symbol base_symbol, plural_symbol
|
56
|
+
|
57
|
+
# make sure singular and plural structures exist
|
58
|
+
dict[symbol] ||= []
|
59
|
+
|
60
|
+
# make array lengths equal to the max of the common, singular and plural arrays
|
61
|
+
while dict[symbol].length < [symbols.map { |s| dict[s].length }, dict[common_symbol].length].flatten.max
|
62
|
+
dict[symbol] << []
|
63
|
+
end
|
64
|
+
|
65
|
+
# add common words to current word list, respecting syllables and plurality
|
66
|
+
dict[symbol].each_index do |i|
|
67
|
+
if word_type.add_s_target == plural_symbol
|
68
|
+
# currently building a list in which the words should have an 's' added when copying from _common
|
69
|
+
dict[symbol][i] += Dictionary.add_s_to_all(dict[common_symbol][i]) if dict[common_symbol][i]
|
70
|
+
else
|
71
|
+
# not adding an 's' in this case, or building the singular word list
|
72
|
+
dict[symbol][i] += dict[common_symbol][i] if dict[common_symbol][i]
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
|
79
|
+
def self.add_s_to_all(word_list)
|
80
|
+
out = []
|
81
|
+
word_list.each do |word_or_array|
|
82
|
+
if word_or_array.is_a? Array
|
83
|
+
# recursively call again and add the nested array
|
84
|
+
out << Dictionary.add_s_to_all(word_or_array)
|
85
|
+
else
|
86
|
+
out << "#{word_or_array}s"
|
87
|
+
end
|
88
|
+
end
|
89
|
+
out
|
90
|
+
end
|
91
|
+
|
92
|
+
# force load of dictionary from yaml file now
|
93
|
+
def self.load(path = DEFAULT_DICT_PATH)
|
94
|
+
dict = YAML.load_file(File.expand_path(path, File.dirname(__FILE__)))
|
95
|
+
|
96
|
+
WORD_TYPES.each do |k, wt|
|
97
|
+
Dictionary.complete_plurality(dict, wt)
|
98
|
+
end
|
99
|
+
|
100
|
+
#ap dict
|
101
|
+
|
102
|
+
dict
|
103
|
+
end
|
104
|
+
|
105
|
+
# load dictionary if not yet done, using default dictionary yaml path
|
106
|
+
def self.init
|
107
|
+
@@dict ||= load
|
108
|
+
end
|
109
|
+
|
110
|
+
# force load/reload of dictionary, optionally passing a custom path to a dictionary yaml file
|
111
|
+
def self.init!(path = DEFAULT_DICT_PATH)
|
112
|
+
@@dict = load path
|
113
|
+
end
|
114
|
+
|
115
|
+
# if available, returns a random word of the given type and number of syllables
|
116
|
+
def self.get_word(word_type, syllables, plurality = :none)
|
117
|
+
|
118
|
+
Dictionary.init
|
119
|
+
|
120
|
+
# validate word_type
|
121
|
+
return nil unless word_type
|
122
|
+
|
123
|
+
# validate syllables input
|
124
|
+
return nil unless syllables.is_a?(Fixnum) && syllables > 0
|
125
|
+
|
126
|
+
dict_symbol = word_type.dict_symbol plurality
|
127
|
+
if @@dict[dict_symbol] && @@dict[dict_symbol][syllables - 1]
|
128
|
+
word_or_array = @@dict[dict_symbol][syllables - 1].sample
|
129
|
+
while word_or_array.is_a? Array
|
130
|
+
# this item contains a nested list of items (to limit chances of nested item being selected)
|
131
|
+
# sample from nested array and try again to find a word ("leaf node")
|
132
|
+
word_or_array = word_or_array.sample
|
133
|
+
end
|
134
|
+
# current item is a word and not a nested list, return it
|
135
|
+
word_or_array
|
136
|
+
else
|
137
|
+
nil
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
def self.words?(word_type, syllables, plurality = :none)
|
142
|
+
!Dictionary.get_word(word_type, syllables, plurality).nil?
|
143
|
+
end
|
144
|
+
|
145
|
+
end
|
146
|
+
|
147
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require File.expand_path('haiku_template.rb', File.dirname(__FILE__))
|
2
|
+
|
3
|
+
module HaikuGadget
|
4
|
+
|
5
|
+
# returns a haiku as either a single string or an array of strings, based on whether a delimiter was provided
|
6
|
+
def self.haiku(delim = nil, haiku_template = nil)
|
7
|
+
if delim.nil?
|
8
|
+
# no delimiter, return array
|
9
|
+
haiku_lines haiku_template
|
10
|
+
else
|
11
|
+
# use delimiter and return a single string
|
12
|
+
haiku_string delim, haiku_template
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
# return a single string where the lines are separated by the provided delimiter
|
17
|
+
def self.haiku_string(delim, haiku_template)
|
18
|
+
haiku_lines(haiku_template).join delim
|
19
|
+
end
|
20
|
+
|
21
|
+
# return haiku as an array of lines (strings)
|
22
|
+
def self.haiku_lines(haiku_template)
|
23
|
+
if haiku_template.nil?
|
24
|
+
HaikuTemplate.new.generate
|
25
|
+
else
|
26
|
+
haiku_template.generate
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.top_line(word_templates = nil)
|
31
|
+
HaikuGadget.random_line(0, word_templates)
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.middle_line(word_templates = nil)
|
35
|
+
HaikuGadget.random_line(1, word_templates)
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.bottom_line(word_templates = nil)
|
39
|
+
HaikuGadget.random_line(2, word_templates)
|
40
|
+
end
|
41
|
+
|
42
|
+
# return just a single random line
|
43
|
+
def self.random_line(row_index, word_templates = nil)
|
44
|
+
fail "invalid row_index: #{row_index.to_s}" unless (0..2).include?(row_index)
|
45
|
+
if word_templates.nil?
|
46
|
+
# get a random template defined for the current row
|
47
|
+
word_templates = HaikuTemplate.new.template_matrix[row_index]
|
48
|
+
end
|
49
|
+
# generate a HaikuTemplate object that only contains a single line with the desired template
|
50
|
+
haiku_template = HaikuTemplate.new [word_templates]
|
51
|
+
haiku_template.generate[0]
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
@@ -0,0 +1,228 @@
|
|
1
|
+
require File.expand_path('word_template.rb', File.dirname(__FILE__))
|
2
|
+
require File.expand_path('dictionary.rb', File.dirname(__FILE__))
|
3
|
+
|
4
|
+
module HaikuGadget
|
5
|
+
|
6
|
+
class HaikuTemplate
|
7
|
+
|
8
|
+
attr_reader :template_matrix
|
9
|
+
|
10
|
+
COMMON_LINES = [
|
11
|
+
[
|
12
|
+
WordTemplate.new(:determiner, 0, :any, 1),
|
13
|
+
WordTemplate.new(:noun, 1, :any, 1),
|
14
|
+
WordTemplate.new(:verb, 1, :any, 1),
|
15
|
+
WordTemplate.new(:mass_noun_determiner),
|
16
|
+
WordTemplate.new(:mass_noun, 1)
|
17
|
+
], [
|
18
|
+
WordTemplate.new(:adverb, 2),
|
19
|
+
WordTemplate.new(:verb, 1, :plural),
|
20
|
+
WordTemplate.new(:adjective, 0, :plural),
|
21
|
+
WordTemplate.new(:noun, 1, :plural)
|
22
|
+
], [
|
23
|
+
WordTemplate.new(:mass_noun_determiner),
|
24
|
+
WordTemplate.new(:adjective, 0, :common),
|
25
|
+
WordTemplate.new(:mass_noun, 1),
|
26
|
+
WordTemplate.new(:to_be, 1, :singular),
|
27
|
+
WordTemplate.new(:adjective, 1, :any)
|
28
|
+
], [
|
29
|
+
WordTemplate.new(:determiner, 0, :any, 1),
|
30
|
+
WordTemplate.new(:noun, 1, :any, 1),
|
31
|
+
WordTemplate.new(:verb, 1, :any, 1),
|
32
|
+
WordTemplate.new(:determiner, 0, :any, 2),
|
33
|
+
WordTemplate.new(:noun, 1, :any, 2)
|
34
|
+
], [
|
35
|
+
WordTemplate.new(:determiner, 0, :any, 1),
|
36
|
+
WordTemplate.new(:adjective, 0, :any, 1),
|
37
|
+
WordTemplate.new(:noun, 1, :any, 1),
|
38
|
+
WordTemplate.custom('of', 1),
|
39
|
+
WordTemplate.new(:mass_noun, 1),
|
40
|
+
WordTemplate.new(:verb_self, 1, :any, 1)
|
41
|
+
], [
|
42
|
+
WordTemplate.custom(%w(i we they), 1),
|
43
|
+
WordTemplate.new(:verb, 1, :plural),
|
44
|
+
WordTemplate.new(:determiner, 0, :any, 2),
|
45
|
+
WordTemplate.new(:adjective, 0, :any, 2),
|
46
|
+
WordTemplate.new(:noun, 1, :any, 2),
|
47
|
+
WordTemplate.new(:adverb)
|
48
|
+
]
|
49
|
+
]
|
50
|
+
|
51
|
+
MIDDLE_LINES = [
|
52
|
+
[
|
53
|
+
WordTemplate.new(:transition_join),
|
54
|
+
WordTemplate.new(:determiner, 0, :any, 1),
|
55
|
+
WordTemplate.new(:adjective, 0, :any, 1),
|
56
|
+
WordTemplate.new(:noun, 1, :any, 1),
|
57
|
+
WordTemplate.new(:verb_self, 1, :any, 1),
|
58
|
+
WordTemplate.new(:adverb)
|
59
|
+
]
|
60
|
+
]
|
61
|
+
|
62
|
+
BOTTOM_LINES = [
|
63
|
+
[
|
64
|
+
WordTemplate.new(:transition_join),
|
65
|
+
WordTemplate.new(:adjective, 0, :plural, 1),
|
66
|
+
WordTemplate.new(:noun, 1, :plural, 1),
|
67
|
+
WordTemplate.new(:verb_self, 1, :plural, 1)
|
68
|
+
]
|
69
|
+
]
|
70
|
+
|
71
|
+
ALL_TOP_LINES = [
|
72
|
+
COMMON_LINES
|
73
|
+
].flatten(1)
|
74
|
+
|
75
|
+
ALL_MIDDLE_LINES = [
|
76
|
+
COMMON_LINES,
|
77
|
+
MIDDLE_LINES
|
78
|
+
].flatten(1)
|
79
|
+
|
80
|
+
ALL_BOTTOM_LINES = [
|
81
|
+
COMMON_LINES,
|
82
|
+
BOTTOM_LINES
|
83
|
+
].flatten(1)
|
84
|
+
|
85
|
+
def initialize(template_matrix = nil)
|
86
|
+
# generate a template_matrix randomly if one was not provided
|
87
|
+
if template_matrix.nil?
|
88
|
+
template_matrix = [
|
89
|
+
HaikuTemplate.random_template(ALL_TOP_LINES),
|
90
|
+
HaikuTemplate.random_template(ALL_MIDDLE_LINES),
|
91
|
+
HaikuTemplate.random_template(ALL_BOTTOM_LINES)
|
92
|
+
]
|
93
|
+
end
|
94
|
+
# clone the two-dimensional array (so syllable counts can be changed)
|
95
|
+
@template_matrix = template_matrix.map { |tm| tm.map { |wt| wt.clone } }
|
96
|
+
complete_template
|
97
|
+
end
|
98
|
+
|
99
|
+
def generate
|
100
|
+
lines = []
|
101
|
+
@template_matrix.each do |word_templates|
|
102
|
+
words = HaikuTemplate.real_words_from_templates word_templates
|
103
|
+
lines << words.join(' ')
|
104
|
+
end
|
105
|
+
lines
|
106
|
+
end
|
107
|
+
|
108
|
+
private
|
109
|
+
|
110
|
+
def complete_template
|
111
|
+
complete_template_plurality
|
112
|
+
complete_template_syllables
|
113
|
+
end
|
114
|
+
|
115
|
+
def complete_template_plurality
|
116
|
+
@template_matrix.each do |word_templates|
|
117
|
+
obj_pluralities = []
|
118
|
+
word_templates.each do |word_template|
|
119
|
+
if word_template.plurality == :any
|
120
|
+
# need to pick a plurality for this word
|
121
|
+
if word_template.obj_num > 0
|
122
|
+
# this word is referencing an object, and its plurality can be randomized
|
123
|
+
unless obj_pluralities[word_template.obj_num]
|
124
|
+
# this word's plurality has not already been determined via another word on this line
|
125
|
+
obj_pluralities[word_template.obj_num] = [:singular, :plural].sample
|
126
|
+
end
|
127
|
+
word_template.plurality = obj_pluralities[word_template.obj_num]
|
128
|
+
else
|
129
|
+
word_template.plurality = [:singular, :plural].sample
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def complete_template_syllables
|
137
|
+
syllables = [5, 7, 5]
|
138
|
+
@template_matrix.each_index do |i|
|
139
|
+
while HaikuTemplate.row_syllables(@template_matrix[i]) < syllables[i]
|
140
|
+
increased_syllable_index = HaikuTemplate.increase_row_syllable(@template_matrix[i])
|
141
|
+
break if increased_syllable_index.nil?
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def self.real_words_from_templates(word_templates)
|
147
|
+
words = []
|
148
|
+
word_templates.each do |word_template|
|
149
|
+
if word_template.syllables > 0
|
150
|
+
word = word_template.word_type.get_word(
|
151
|
+
word_template.syllables,
|
152
|
+
word_template.plurality
|
153
|
+
)
|
154
|
+
words << word
|
155
|
+
end
|
156
|
+
end
|
157
|
+
HaikuTemplate.convert_a_to_an words
|
158
|
+
words
|
159
|
+
end
|
160
|
+
|
161
|
+
# where necessary, convert 'a' to 'an'
|
162
|
+
def self.convert_a_to_an(words)
|
163
|
+
words.each_index do |i|
|
164
|
+
if words[i] == 'a' && (i < (words.length - 1)) && %w(a e i o u).include?(words[i + 1].slice(0))
|
165
|
+
# current word is 'a', there are more words after this one, and the next one starts with a, e, i, o or u
|
166
|
+
words[i] = 'an'
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
def self.row_syllables(word_templates)
|
172
|
+
word_templates.map { |w| w.syllables }.inject(:+)
|
173
|
+
end
|
174
|
+
|
175
|
+
def self.increase_row_syllable(word_templates)
|
176
|
+
valid_word_indices = HaikuTemplate.get_valid_word_indices word_templates
|
177
|
+
|
178
|
+
increase_syllable_index = nil
|
179
|
+
loop do
|
180
|
+
increase_syllable_index = HaikuTemplate.increased_row_syllable_index(word_templates, valid_word_indices)
|
181
|
+
break if increase_syllable_index || valid_word_indices.length == 0
|
182
|
+
end
|
183
|
+
if increase_syllable_index
|
184
|
+
word_templates[increase_syllable_index].syllables += 1
|
185
|
+
increase_syllable_index
|
186
|
+
else
|
187
|
+
nil
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
def self.get_valid_word_indices(word_templates)
|
192
|
+
out = []
|
193
|
+
word_templates.each_index do |i|
|
194
|
+
out << i unless word_templates[i].word_type.base_symbol == :custom
|
195
|
+
end
|
196
|
+
out
|
197
|
+
end
|
198
|
+
|
199
|
+
# returns the word index where another syllable can be added (and where dictionary words are available)
|
200
|
+
def self.increased_row_syllable_index(word_templates, valid_word_indices)
|
201
|
+
if valid_word_indices.length > 0
|
202
|
+
word_index = valid_word_indices.sample
|
203
|
+
if word_templates[word_index].word_type.words?(
|
204
|
+
word_templates[word_index].syllables + 1,
|
205
|
+
word_templates[word_index].plurality
|
206
|
+
)
|
207
|
+
word_index
|
208
|
+
else
|
209
|
+
# dictionary has no words of this type, remove this index so it isn't checked in the future
|
210
|
+
valid_word_indices.delete word_index
|
211
|
+
nil
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
def self.random_template(templates)
|
217
|
+
template_or_array = templates.sample
|
218
|
+
if template_or_array[0].is_a? Array
|
219
|
+
# if NESTED object is an array, recurse
|
220
|
+
HaikuTemplate.random_template template_or_array
|
221
|
+
else
|
222
|
+
template_or_array
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
end
|
227
|
+
|
228
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require File.expand_path('word_type.rb', File.dirname(__FILE__))
|
2
|
+
|
3
|
+
module HaikuGadget
|
4
|
+
|
5
|
+
class WordTemplate
|
6
|
+
|
7
|
+
attr_reader :word_type, :obj_num
|
8
|
+
attr_accessor :syllables, :plurality
|
9
|
+
|
10
|
+
def initialize(base_symbol_or_word_type, syllables = 0, plurality = :none, obj_num = 0)
|
11
|
+
|
12
|
+
if base_symbol_or_word_type.is_a? HaikuGadget::WordType
|
13
|
+
# use provided (custom) WordType
|
14
|
+
word_type = base_symbol_or_word_type
|
15
|
+
else
|
16
|
+
# look up word type based on symbol
|
17
|
+
word_type = Dictionary::WORD_TYPES[base_symbol_or_word_type]
|
18
|
+
end
|
19
|
+
|
20
|
+
fail 'unknown word type' unless word_type
|
21
|
+
|
22
|
+
# check if template plurality needs to be set or changed
|
23
|
+
if word_type.can_be_plural
|
24
|
+
plurality = :any if plurality == :none
|
25
|
+
else
|
26
|
+
plurality = :none
|
27
|
+
end
|
28
|
+
|
29
|
+
@word_type = word_type
|
30
|
+
@syllables = syllables
|
31
|
+
@plurality = plurality
|
32
|
+
@obj_num = obj_num
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.custom(word_list, syllables)
|
37
|
+
|
38
|
+
WordTemplate.new WordType.custom(word_list), syllables
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module HaikuGadget
|
2
|
+
|
3
|
+
class WordType
|
4
|
+
|
5
|
+
attr_reader :base_symbol, :can_be_plural, :add_s_target
|
6
|
+
|
7
|
+
def initialize(base_symbol, can_be_plural = false, add_s_target = nil, custom_words = [])
|
8
|
+
@base_symbol = base_symbol
|
9
|
+
@can_be_plural = can_be_plural
|
10
|
+
@add_s_target = add_s_target
|
11
|
+
|
12
|
+
# make sure custom_words is an array (allows convenient input of a single string)
|
13
|
+
@custom_words = custom_words.is_a?(Array) ? custom_words : [custom_words]
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.custom(custom_words = [])
|
17
|
+
WordType.new :custom, false, nil, custom_words
|
18
|
+
end
|
19
|
+
|
20
|
+
# translates the base symbol type into a _singular or _plural one if necessary
|
21
|
+
# for doing dictionary lookups
|
22
|
+
def dict_symbol(plurality)
|
23
|
+
# do not allow plurality of :none for a word that has plurality
|
24
|
+
# this is a redundant error check and should not happen
|
25
|
+
plurality = [:singular, :plural].sample if @can_be_plural && plurality == :none
|
26
|
+
|
27
|
+
if @can_be_plural && [:singular, :plural].include?(plurality)
|
28
|
+
# word can be plural
|
29
|
+
"#{@base_symbol.to_s}_#{plurality.to_s}".to_sym
|
30
|
+
else
|
31
|
+
# word type is not relevent to plurality
|
32
|
+
@base_symbol
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def get_word(syllables, plurality = :none)
|
37
|
+
if base_symbol == :custom
|
38
|
+
@custom_words.sample
|
39
|
+
else
|
40
|
+
Dictionary.get_word self, syllables, plurality
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def words?(syllables, plurality = :none)
|
45
|
+
if base_symbol == :custom
|
46
|
+
!get_word(syllables, plurality).nil?
|
47
|
+
else
|
48
|
+
Dictionary.words? self, syllables, plurality
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
end
|
data/lib/tasks/.keep
ADDED
File without changes
|
data/lib/words.yml
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
---
|
2
|
+
:transition_join: [
|
3
|
+
[so, and, or, plus, but, yet, while, when, if, then, thus, hence, now]
|
4
|
+
]
|
5
|
+
|
6
|
+
:determiner_common: [
|
7
|
+
[the, [no, some, your, my, his, her, its, their, our]]
|
8
|
+
]
|
9
|
+
:determiner_singular: [
|
10
|
+
[a, [this, that]]
|
11
|
+
]
|
12
|
+
:determiner_plural: [
|
13
|
+
[all, both, few, most, [these, those]]
|
14
|
+
]
|
15
|
+
|
16
|
+
:to_be_singular: [
|
17
|
+
[is, was],
|
18
|
+
[[is not, 'isn''t'], [was not, 'wasn''t'], will be]
|
19
|
+
]
|
20
|
+
:to_be_plural: [
|
21
|
+
[are, were],
|
22
|
+
[[are not, 'aren''t'], [were not, 'weren''t'], will be]
|
23
|
+
]
|
24
|
+
|
25
|
+
:adjective_common: [
|
26
|
+
[red, fresh, weird, burnt, white, flat, round, weak, old, new, young, swell, sweet, dazed, vague, warmed, cool, strong, blue, clear, soft, hard, black, big, small, tight, loose, long, short, wry, young, green, bold, good, bad, kind, mean, wet, dry, free, light, dark, dim, wise, grim, huge, worn, numb, wild, tall, short, hot, cold, sad, gray, green, gold, raw, rich, poor, bored, dull, calm, smart, dumb, grand, keen, bright, bent, foul, close, chrome, low, last, first, next, fun, high, late, quaint, side, top, lost, cute, real, strict, [north, west, south, east]],
|
27
|
+
[orange, mental, tired, gloomy, murky, salty, doomed, ecstatic, balanced, frayed, frosted, confused, opened, tasty, frozen, boiling, slimy, failed, crazed, oblong, broken, silver, faulty, limestone, opaque, silly, spinning, busted, lazy, flying, awesome, folded, rhythmic, floating, smoking, twisted, wispy, uncooked, complex, bubbly, immobile, bankrupt, moving, crispy, laundered, rounded, cleaned, ample, dirty, catered, constrained, cosmic, choking, ballistic, red-faced, bizarre, sanded, roasted, inverted, spastic, dapper, swanky, able, fabled, stable, leaning, correct, staggered, wrong, curved, open, evil, closed, edgy, pricey, costly, fancy, stranded, meager, modest, humble, slimy, simple, unkind, unwound, teenage, heavy, standard, hollow, eager, rotten, unwise, grounded, boring, crazy, major, minor, naive, valid, random, happy, endless, human, splendid, certain, somber, livid, lonely, jealous, dreary, lovely, cheerful, secure, renowned, spicy, drunken, bulky, breaded, better, shorter, smaller, larger, smarter, faster, longer, distant, wealthy, dismayed, vital, colored, abstract, vivid, ancient, bitter, sour, airy, timely, sunny, current, funky, skinny, bloody, girly, boyish, roomy, royal, marine, varied, fuzzy, helpful, crafty, [northern, western, southern, eastern]],
|
28
|
+
[redundant, respected, uncovered, populous, required, unstable, communist, communal, religious, circular, feminine, masculine, incorrect, underwater, embarrassed, misshapen, glorious, hovering, uncaring, expanded, insulted, discovered, commissioned, considered, opulent, casual, ultimate, imminent, exacting, creative, furious, destructive, modulated, digital, analog, essential, albino, nuclear, atomic, chocolate, overweight, invalid, possible, advertised, natural, terrific, pot-bellied, amazing, confident, exacting, finished, primary, lunatic, satisfied, impressive, lunatic, noteworthy, suitable, musical, eternal, skydiving, expected, parallel],
|
29
|
+
[undulating, incredible, unforgiving, acceptable, elaborate, necessary, stimulated, measurable, recommended, mandatory, honorable, identical, overstated, altruistic, generated, extraneous, aluminum, obfuscated, appropriate, symbiotic, calculated, mysterious, unknowable, beautiful, contemplative, incapable, overbearing, high quality, low quality, microbial, questionable, knowledgeable, elemental, hilarious, inferior, meticulous]
|
30
|
+
]
|
31
|
+
:adjective_singular: [
|
32
|
+
[one]
|
33
|
+
]
|
34
|
+
:adjective_plural: [
|
35
|
+
[two, three, four, [five, six, eight, nine, ten, twelve]],
|
36
|
+
[zero, many, seven, twenty, thirty, [thirteen, fourteen, fifteen, sixteen, eighteen, nineteen, forty, fifty]],
|
37
|
+
[one hundred, several, numerous]
|
38
|
+
]
|
39
|
+
|
40
|
+
:noun_common: [
|
41
|
+
[thing, bug, head, toe, eye, phone, web, ball, hand, ear, sheet, bed, car, truck, plane, brain, day, sun, square, bike, lake, creek, stone, moon, shoe, yacht, field, task, thought, sword, wig, boy, girl, prince, kid, pet, fig, moth, dog, bun, cat, bat, oar, lip, grain, soul, ape, duck, ray, beam, leg, rat, bear, boar, boat, door, goon, gob, plank, brick, stake, cube, ant, cord, bowl, chord, crate, wire, wreath, spear, isle, tree, wheel, hut, hat, gnat, spot, pond, cork, star, tribe, wine, beer, drink, film, bum, cup, rock, hook, path, king, queen, jack, mob, skill, job, house, cow, chair, disk, pit, hole, card, face, hill, mound, knob, zoo, light, fool, pill, quark, cloud, glove, sock, boot, slave, shrub, cook, pie, bird, snake, worm, tank, pen, weed, flute, nest, pot, bee, pan, gem, mom, dad, son, jeep, train, nun, pal, month, year, week, poem, shark, yak, joke, owl, skunk, worm, egg, cake, pea, grape, bean, spore, seed, fruit, wing, fire, world, heart, rod, board, nail, end, ring, sea, key, god, word, night, knight, bone, room, toy, side, top, book, name, game, ship, test, park, time, bag, school, clone, shop, store],
|
42
|
+
[zombie, ninja, pirate, monkey, robot, hot dog, space ship, rain drop, circle, tv, flower, typhoon, garden, cookie, taco, gyro, mountain, painting, river, meadow, island, message, morsel, marble, mitten, trombone, nugget, chicken, donkey, llama, hamster, raisin, nation, rocket, bottle, anvil, sunset, muskrat, treasure, coastline, building, lighthouse, concept, forest, python, dinner, hammer, robber, jacket, singer, puppet, valley, comet, scooter, joker, pebble, kayak, gorilla, airplane, table, atom, movie, poster, fountain, missile, pimple, player, shovel, window, rooster, biscuit, raven, eagle, question, vampire, peon, otter, camel, suburb, towel, turkey, pencil, planet, viking, squirrel, snowboard, dweller, lemon, photo, item, skillet, mother, father, brother, sister, elder, aardvark, apple, object, pickle, staple, wizard, raccoon, tadpole, spigot, daughter, mantra, pizza, calzone, vision, haiku, pixel, onion, glacier, penguin, cobra, dolphin, spider, trumpet, donut, ion, aura, geezer, freedom, attempt, pigeon, teacher, [sunday, monday, tuesday, wednesday, thursday, friday, saturday]],
|
43
|
+
[samurai, spatula, tornado, hurricane, restaurant, computer, radio, stereo, commuter, newspaper, hairdryer, photograph, sombrero, burrito, telephone, animal, bicycle, dinosaur, iguana, kangaroo, umbrella, hiking boot, dishwasher, asteroid, meteor, cruise liner, oil tanker, apple pie, gorilla, tricycle, artichoke, musician, visitor, universe, disaster, piano, canteloupe, pyramid, article, location, banana],
|
44
|
+
[fortune cookie, ecosystem, obligation, generator, generation, ambassador, elevator, watermelon, convertible, calculator, harmonica, operation, invitation, kindergarten, helicopter, alligator, caterpillar, constellation, germination, politician, corporation, advertisement, declaration, astronomer, variation, civilization, perimeter, population, denominator, semicircle, operator, aquarium, disappointment, kaleidoscope, television, orangutan, washing machine, environment]
|
45
|
+
]
|
46
|
+
:noun_singular: [
|
47
|
+
[fish, man, child, box, sky, beach, sheep, church, mouse, fox, goose, wish, life],
|
48
|
+
[hobby, woman, baby, country, princess, person, hero, potato],
|
49
|
+
[enemy, remedy, nebula, library, factory, mosquito, buffalo],
|
50
|
+
[bacteria, reality, discovery, super hero, territory, deficiency, activity, calamity, emergency]
|
51
|
+
]
|
52
|
+
:noun_plural: [
|
53
|
+
[fish, men, skies, sheep, mice, geese, lives],
|
54
|
+
[women, children, babies, countries, cities, boxes, cattle, people, grizzlies, heroes, foxes, beaches, churches, wishes],
|
55
|
+
[enemies, hobbies, remedies, libraries, factories, potatoes, mosquitoes, buffaloes],
|
56
|
+
[bacteria, realities, discoveries, super heroes, territories, activities, calamities, emergencies]
|
57
|
+
]
|
58
|
+
|
59
|
+
:mass_noun_determiner: [
|
60
|
+
[the, [all, some, no], [your, my, his, her, our, their]]
|
61
|
+
]
|
62
|
+
|
63
|
+
:mass_noun: [
|
64
|
+
[fun, love, snow, funk, earth, space, home, dust, pain, life, health, death, loss, thought, beer, wine, dirt, fire, flame, style, lore, wind, force, fog, haze, time, war, peace, doom, food, art, gloom, hope, ice, oil, gold, light, cheese, grass, breath, steel, iron, stone, zen, stuff, hair, soup, sense, air, gas, ground, foam, glass, wealth, slime, cloth, tea, juice, fruit, jazz, heat, speed, glue, noise, wood, milk, cake, rice, work, grief, fish, lust, sleep, heart, night, skin, blood, sand, math, rain, youth, lore, grace, corn, bread, glee, mist, jive, help],
|
65
|
+
[metal, essence, power, magic, evil, peril, disease, vapor, butter, sugar, darkness, fortune, soda, success, failure, water, passion, wonder, beauty, reason, fabric, lava, jello, ketchup, coffee, jelly, ice cream, sadness, goodness, physics, money, ethics, traffic, plastic, dancing, anger, danger, softness, friendship, trouble, culture, virtue, fuel, music, freedom, cornbread, lightning, sorrow, mustard, fluid, liquid, knowledge],
|
66
|
+
[happiness, gravity, desire, misfortune, pestilence, certainty, mystery, energy, chocolate, honesty, poverty, laziness, chemistry, furniture, equipment, violence, liberty, jealousy, gelato, intention, religion],
|
67
|
+
[society, community, contemplation, inconvenience, humanity, morality, information, intelligence, stupidity, geometry]
|
68
|
+
]
|
69
|
+
|
70
|
+
:verb_common: [
|
71
|
+
[bloom, drain, pat, climb, bend, give, take, pour, yank, clip, spread, build, shape, hate, throw, find, hear, see, smell, taste, eat, like, wake, tempt, smack, fold, farm, sip, lure, rip, rock, poke, warm, pull, grab, shove, pet, cut, get, bang, bust, bet, trick, lick, steal, boil, toast, dunk, gulp, meet, dig, form, roll, bathe, trap, treat, feed, hack, kick, heal, blast, lift, draw, cook, shake, bring, see, want, need, feel, love, hug, break, make, shock, paint, gain, kill, fund, hire, read, bake, own, rob, herd, rent, move, pay, jab, stop, start, turn, tear, fire, eye, scare, ask, win, make, ship, test, ride, school, clone, train, drive, know, buy, store, save, help],
|
72
|
+
[consume, destroy, attack, nurture, explore, open, construct, befriend, explain, target, retain, prevent, protest, direct, procure, locate, staple, strangle, topple, avoid, reveal, survey, maintain, fasten, harden, straighten, offer, transform, tickle, question, deceive, mislead, support, become, revive, connect, iron, annoy, forget, handle, answer, inspect, behold, design, acquire, obtain, believe, dazzle, honor, master, gather, savor, adjust, expect, create, instruct, afford, succeed],
|
73
|
+
[imagine, examine, interrupt, activate, agitate, animate, apprehend, calibrate, captivate, celebrate, complicate, decimate, decipher, dishonor, dominate, enliven, generate, jettison, isolate, medicate, nominate, orient, overwhelm, recycle, terminate, violate, discover]
|
74
|
+
]
|
75
|
+
:verb_singular: [
|
76
|
+
[soothes],
|
77
|
+
[eases, nudges, uses, raises, slices, falls on, dreams of, jumps over, looks at, looks for, studies, tosses, touches, coaxes, pushes, reaches, punches, cares for, ties up, sticks to, goes to, swarms on, flails at, cooks for, kisses, smooches, speaks to, quests for, raves about, sits on, waves to, shines on, mixes, watches, copies, marries, senses, closes, sings to, smiles at, asks for, hopes for, toys with, plays with, floats on, lives with, steps on, jives with, hops on],
|
78
|
+
[amazes, cares about, notifies, objects to, condenses, beautifies, glorifies, liquefies, nullifies, occupies, purifies, satisfies, stupefies, wishes for, thinks about, writes about]
|
79
|
+
]
|
80
|
+
:verb_plural: [
|
81
|
+
[ease, nudge, use, raise, slice, study, toss, touch, coax, push, reach, punch, kiss, smooch, mix, watch, copy, sense, sooth, close],
|
82
|
+
[amaze, fall on, dream of, jump over, look at, look for, finish, care for, approach, tie up, stick to, go to, swarm on, flail at, cook for, dance with, dance for, speak to, quest for, rave about, sit on, wave to, shine on, condense, marry, advise, sing to, smile at, ask for, hope for, wish for, toy with, play with, think about, float on, lives on, step on, jive with, hop on],
|
83
|
+
[care about, notify, object to, beautify, glorify, liquefy, nullify, occupy, purify, satisfy, stupefy, vandalize, vaporize, minimize, maximize, encourage, equalize, pulverize, write about]
|
84
|
+
]
|
85
|
+
|
86
|
+
:verb_self_common: [
|
87
|
+
[wake, jump, speed, climb, live, hope, fail, float, fall, slow, creep, sleep, groan, moan, coast, suck, walk, run, wait, think, land, scream, crawl, play, smile, glow, wave, dream, yell, work, feel, nap, quake, whine, trek, learn, weep, sob, speak, hide, pose, laugh, bathe, burn, grow, shrink, feast, warn, stray, peek, creak, flow, come, feed, cope, heal, race, read, dig, dwell, move, pray, gawk, breed, sag, spit, stand, stop, swerve, eat, lust, shine, end, bleed, drop, open, shake, start, fart, tear, turn, sail, sing, ask, sin, point, ail, flail, fold, die, smell, groove, shout, lie, dine, win, write, train, drive, know, jive, hop, shop, paint],
|
88
|
+
[survive, ponder, wonder, travel, transform, falter, wallow, improve, believe, boogie, crumble, giggle, complain, forget, persist, explore, exist, arrive, await, agree, connect, engage, haggle, return, rotate, resist, dabble, murmur, mature, protest, gossip, growl, begin, approve, clamber, attack, perform, abide, achieve, succeed],
|
89
|
+
[concentrate, speculate, hesitate, meditate, calculate, celebrate, co-exist, consider, continue, deviate, disagree, disbelieve, disconnect, elevate, imagine, meander, navigate, overact, postulate, propagate, radiate, recover, replicate, duplicate, surrender, terminate, understand, undulate, hibernate, self-destruct]
|
90
|
+
]
|
91
|
+
:verb_self_singular: [
|
92
|
+
[goes, flies, cries],
|
93
|
+
[sits down, lies down, wakes up, freezes, bounces, replies, responds, gazes, loses, rises, rushes, marches, pauses, crashes, watches, dances, rages, rushes, breaks up],
|
94
|
+
[simplifies, testifies, relaxes, approaches, emerges]
|
95
|
+
]
|
96
|
+
:verb_self_plural: [
|
97
|
+
[go, fly, cry, freeze, gaze, lose, rise, rush, march, pause, crash, watch, dance, rage, rush],
|
98
|
+
[sit down, lie down, wake up, approach, reply, respond, relax, collapse, break up, emerge],
|
99
|
+
[simplify, stabilize, testify]
|
100
|
+
]
|
101
|
+
|
102
|
+
:adverb: [
|
103
|
+
[great, well, good, bad, fast, slow, up, down, soon, now, nice, left, right, wrong, some, near, far, hard, soft],
|
104
|
+
[always, badly, blindly, boldly, bravely, brightly, clearly, deftly, kindly, loosely, madly, never, oddly, often, only, poorly, sadly, promptly, quickly, rarely, really, rudely, safely, seldom, slowly, sometimes, warmly, yearly],
|
105
|
+
[angrily, anxiously, awkwardly, boastfully, cheerfully, crazily, doubtfully, eagerly, evenly, exactly, finally, foolishly, frantically, frequently, gleefully, gracefully, happily, hastily, honestly, hourly, hungrily, jealously, lazily, perfectly, politely, rapidly, tenderly, totally, weekly, wildly, royally]
|
106
|
+
]
|
@@ -0,0 +1,152 @@
|
|
1
|
+
module HaikuGadget
|
2
|
+
|
3
|
+
describe 'HaikuGadget' do
|
4
|
+
|
5
|
+
describe 'with default dictionary' do
|
6
|
+
|
7
|
+
dict_path = '../../lib/words.yml'
|
8
|
+
|
9
|
+
before(:each) do
|
10
|
+
Dictionary.init! dict_path
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'should have various types of words' do
|
14
|
+
[:noun, :verb, :adjective].each do |valid_symbol|
|
15
|
+
word_type = Dictionary::WORD_TYPES[valid_symbol]
|
16
|
+
|
17
|
+
# check words? method for true/false
|
18
|
+
expect(word_type.words? 1).to eq(true)
|
19
|
+
|
20
|
+
# check get_words method for actual string response
|
21
|
+
expect(word_type.get_word 1).to be_kind_of(String)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should not have a non-existant word type' do
|
26
|
+
[:doesnt_exist, :also_is_wrong, nil].each do |invalid_symbol|
|
27
|
+
invalid_word_type = Dictionary::WORD_TYPES[invalid_symbol]
|
28
|
+
|
29
|
+
# check words? method for true/false
|
30
|
+
expect(Dictionary.words? invalid_word_type, 1).to eq(false)
|
31
|
+
|
32
|
+
# get_word should return nil
|
33
|
+
expect(Dictionary.get_word invalid_word_type, 1).to be_nil
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'should fail if asking for an invalid number (or data type) of syllables' do
|
38
|
+
[:noun, :invalid_word_type, nil].each do |symbol|
|
39
|
+
word_type = Dictionary::WORD_TYPES[symbol]
|
40
|
+
|
41
|
+
# check both valid and invalid word type symbols
|
42
|
+
[0, -1, 9, 'abc', nil, 2.5].each do |invalid_syllables|
|
43
|
+
# check words? method for true/false
|
44
|
+
expect(Dictionary.words? word_type, invalid_syllables).to eq(false)
|
45
|
+
|
46
|
+
# get_word should return nil
|
47
|
+
expect(Dictionary.get_word word_type, invalid_syllables).to be_nil
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
describe 'with single possibility test dictionary' do
|
55
|
+
# these tests use a yaml file in which the randomness is removed because
|
56
|
+
# there is only one word of each type in the dictionary
|
57
|
+
|
58
|
+
dict_path = '../../spec/test_words_single.yml'
|
59
|
+
|
60
|
+
haiku_template = HaikuTemplate.new [
|
61
|
+
[
|
62
|
+
WordTemplate.new(:adjective, 1, :singular, 1), # red
|
63
|
+
WordTemplate.new(:noun, 1, :singular, 1), # thing
|
64
|
+
WordTemplate.new(:verb_self, 3, :singular, 1) # meditates
|
65
|
+
], [
|
66
|
+
WordTemplate.new(:determiner, 1, :plural, 1), # the
|
67
|
+
WordTemplate.new(:noun, 3, :plural, 1), # samurais
|
68
|
+
WordTemplate.new(:verb, 1, :plural, 1), # see
|
69
|
+
WordTemplate.new(:noun, 2, :singular, 2) # zombie
|
70
|
+
], [
|
71
|
+
WordTemplate.new(:adjective, 2, :any, 1), # orange
|
72
|
+
WordTemplate.new(:noun, 2, :any, 1), # zombie(s)
|
73
|
+
WordTemplate.new(:verb_self, 1, :any, 1) # fight(s)
|
74
|
+
]
|
75
|
+
]
|
76
|
+
|
77
|
+
before(:each) do
|
78
|
+
Dictionary.init! dict_path
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'should return a predictable haiku (when generated all at once)' do
|
82
|
+
|
83
|
+
10.times do
|
84
|
+
# do 10 times so the plurality randomization hits multiple possibilities
|
85
|
+
haiku_lines = HaikuGadget.haiku_lines haiku_template
|
86
|
+
|
87
|
+
expect(haiku_lines[0]).to eq('red thing meditates')
|
88
|
+
expect(haiku_lines[1]).to eq('the samurais see zombie')
|
89
|
+
|
90
|
+
# third line can randomly be one of two options
|
91
|
+
last_lines = ['orange zombie fights', 'orange zombies fight']
|
92
|
+
expect(last_lines).to include(haiku_lines[2])
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'should return a predictable haiku (when lines are generated individually)' do
|
98
|
+
|
99
|
+
10.times do
|
100
|
+
# do 10 times so the plurality randomization hits multiple possibilities
|
101
|
+
top_line = HaikuGadget.top_line haiku_template.template_matrix[0]
|
102
|
+
middle_line = HaikuGadget.middle_line haiku_template.template_matrix[1]
|
103
|
+
bottom_line = HaikuGadget.bottom_line haiku_template.template_matrix[2]
|
104
|
+
|
105
|
+
haiku = [top_line, middle_line, bottom_line].join(' | ')
|
106
|
+
|
107
|
+
valid_haikus = [
|
108
|
+
'red thing meditates | the samurais see zombie | orange zombie fights',
|
109
|
+
'red thing meditates | the samurais see zombie | orange zombies fight'
|
110
|
+
]
|
111
|
+
|
112
|
+
expect(valid_haikus).to include(haiku)
|
113
|
+
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
118
|
+
|
119
|
+
describe 'with deeply-nested test dictionary' do
|
120
|
+
|
121
|
+
dict_path = '../../spec/test_words_nested.yml'
|
122
|
+
|
123
|
+
before(:each) do
|
124
|
+
Dictionary.init! dict_path
|
125
|
+
end
|
126
|
+
|
127
|
+
it 'should return a haiku containing expected words' do
|
128
|
+
|
129
|
+
haiku_template = HaikuTemplate.new [
|
130
|
+
[WordTemplate.new(:mass_noun, 5)],
|
131
|
+
[WordTemplate.new(:mass_noun, 7)],
|
132
|
+
[WordTemplate.new(:mass_noun, 5)]
|
133
|
+
]
|
134
|
+
|
135
|
+
haiku = HaikuGadget.haiku nil, haiku_template
|
136
|
+
|
137
|
+
puts "haiku from deeply-nested words: #{haiku.join(' | ')}"
|
138
|
+
|
139
|
+
five_syl_words = %w(personality california university)
|
140
|
+
seven_syl_words = %w(unconventionality territoriality enthusiastically)
|
141
|
+
|
142
|
+
expect(five_syl_words).to include(haiku[0])
|
143
|
+
expect(seven_syl_words).to include(haiku[1])
|
144
|
+
expect(five_syl_words).to include(haiku[2])
|
145
|
+
|
146
|
+
end
|
147
|
+
|
148
|
+
end
|
149
|
+
|
150
|
+
end
|
151
|
+
|
152
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# This file is copied to spec/ when you run 'rails generate rspec:install'
|
2
|
+
ENV["RAILS_ENV"] ||= 'test'
|
3
|
+
require 'spec_helper'
|
4
|
+
require File.expand_path("../../config/environment", __FILE__)
|
5
|
+
require 'rspec/rails'
|
6
|
+
# Add additional requires below this line. Rails is not loaded until this point!
|
7
|
+
|
8
|
+
# Requires supporting ruby files with custom matchers and macros, etc, in
|
9
|
+
# spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are
|
10
|
+
# run as spec files by default. This means that files in spec/support that end
|
11
|
+
# in _spec.rb will both be required and run as specs, causing the specs to be
|
12
|
+
# run twice. It is recommended that you do not name files matching this glob to
|
13
|
+
# end with _spec.rb. You can configure this pattern with the --pattern
|
14
|
+
# option on the command line or in ~/.rspec, .rspec or `.rspec-local`.
|
15
|
+
#
|
16
|
+
# The following line is provided for convenience purposes. It has the downside
|
17
|
+
# of increasing the boot-up time by auto-requiring all files in the support
|
18
|
+
# directory. Alternatively, in the individual `*_spec.rb` files, manually
|
19
|
+
# require only the support files necessary.
|
20
|
+
#
|
21
|
+
# Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f }
|
22
|
+
|
23
|
+
# Checks for pending migrations before tests are run.
|
24
|
+
# If you are not using ActiveRecord, you can remove this line.
|
25
|
+
ActiveRecord::Migration.maintain_test_schema!
|
26
|
+
|
27
|
+
RSpec.configure do |config|
|
28
|
+
# Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
|
29
|
+
config.fixture_path = "#{::Rails.root}/spec/fixtures"
|
30
|
+
|
31
|
+
# If you're not using ActiveRecord, or you'd prefer not to run each of your
|
32
|
+
# examples within a transaction, remove the following line or assign false
|
33
|
+
# instead of true.
|
34
|
+
config.use_transactional_fixtures = true
|
35
|
+
|
36
|
+
# RSpec Rails can automatically mix in different behaviours to your tests
|
37
|
+
# based on their file location, for example enabling you to call `get` and
|
38
|
+
# `post` in specs under `spec/controllers`.
|
39
|
+
#
|
40
|
+
# You can disable this behaviour by removing the line below, and instead
|
41
|
+
# explicitly tag your specs with their type, e.g.:
|
42
|
+
#
|
43
|
+
# RSpec.describe UsersController, :type => :controller do
|
44
|
+
# # ...
|
45
|
+
# end
|
46
|
+
#
|
47
|
+
# The different available types are documented in the features, such as in
|
48
|
+
# https://relishapp.com/rspec/rspec-rails/docs
|
49
|
+
config.infer_spec_type_from_file_location!
|
50
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'haiku_gadget'
|
2
|
+
|
3
|
+
# This file was generated by the `rails generate rspec:install` command. Conventionally, all
|
4
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
5
|
+
# The generated `.rspec` file contains `--require spec_helper` which will cause this
|
6
|
+
# file to always be loaded, without a need to explicitly require it in any files.
|
7
|
+
#
|
8
|
+
# Given that it is always loaded, you are encouraged to keep this file as
|
9
|
+
# light-weight as possible. Requiring heavyweight dependencies from this file
|
10
|
+
# will add to the boot time of your test suite on EVERY test run, even for an
|
11
|
+
# individual file that may not need all of that loaded. Instead, consider making
|
12
|
+
# a separate helper file that requires the additional dependencies and performs
|
13
|
+
# the additional setup, and require it from the spec files that actually need it.
|
14
|
+
#
|
15
|
+
# The `.rspec` file also contains a few flags that are not defaults but that
|
16
|
+
# users commonly want.
|
17
|
+
#
|
18
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
19
|
+
RSpec.configure do |config|
|
20
|
+
# rspec-expectations config goes here. You can use an alternate
|
21
|
+
# assertion/expectation library such as wrong or the stdlib/minitest
|
22
|
+
# assertions if you prefer.
|
23
|
+
config.expect_with :rspec do |expectations|
|
24
|
+
# This option will default to `true` in RSpec 4. It makes the `description`
|
25
|
+
# and `failure_message` of custom matchers include text for helper methods
|
26
|
+
# defined using `chain`, e.g.:
|
27
|
+
# be_bigger_than(2).and_smaller_than(4).description
|
28
|
+
# # => "be bigger than 2 and smaller than 4"
|
29
|
+
# ...rather than:
|
30
|
+
# # => "be bigger than 2"
|
31
|
+
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
|
32
|
+
end
|
33
|
+
|
34
|
+
# rspec-mocks config goes here. You can use an alternate test double
|
35
|
+
# library (such as bogus or mocha) by changing the `mock_with` option here.
|
36
|
+
config.mock_with :rspec do |mocks|
|
37
|
+
# Prevents you from mocking or stubbing a method that does not exist on
|
38
|
+
# a real object. This is generally recommended, and will default to
|
39
|
+
# `true` in RSpec 4.
|
40
|
+
mocks.verify_partial_doubles = true
|
41
|
+
end
|
42
|
+
|
43
|
+
# The settings below are suggested to provide a good initial experience
|
44
|
+
# with RSpec, but feel free to customize to your heart's content.
|
45
|
+
=begin
|
46
|
+
# These two settings work together to allow you to limit a spec run
|
47
|
+
# to individual examples or groups you care about by tagging them with
|
48
|
+
# `:focus` metadata. When nothing is tagged with `:focus`, all examples
|
49
|
+
# get run.
|
50
|
+
config.filter_run :focus
|
51
|
+
config.run_all_when_everything_filtered = true
|
52
|
+
|
53
|
+
# Limits the available syntax to the non-monkey patched syntax that is recommended.
|
54
|
+
# For more details, see:
|
55
|
+
# - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
|
56
|
+
# - http://teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
|
57
|
+
# - http://myronmars.to/n/dev-blog/2014/05/notable-changes-in-rspec-3#new__config_option_to_disable_rspeccore_monkey_patching
|
58
|
+
config.disable_monkey_patching!
|
59
|
+
|
60
|
+
# Many RSpec users commonly either run the entire suite or an individual
|
61
|
+
# file, and it's useful to allow more verbose output when running an
|
62
|
+
# individual spec file.
|
63
|
+
if config.files_to_run.one?
|
64
|
+
# Use the documentation formatter for detailed output,
|
65
|
+
# unless a formatter has already been configured
|
66
|
+
# (e.g. via a command-line flag).
|
67
|
+
config.default_formatter = 'doc'
|
68
|
+
end
|
69
|
+
|
70
|
+
# Print the 10 slowest examples and example groups at the
|
71
|
+
# end of the spec run, to help surface which specs are running
|
72
|
+
# particularly slow.
|
73
|
+
config.profile_examples = 10
|
74
|
+
|
75
|
+
# Run specs in random order to surface order dependencies. If you find an
|
76
|
+
# order dependency and want to debug it, you can fix the order by providing
|
77
|
+
# the seed, which is printed after each run.
|
78
|
+
# --seed 1234
|
79
|
+
config.order = :random
|
80
|
+
|
81
|
+
# Seed global randomization in this process using the `--seed` CLI option.
|
82
|
+
# Setting this allows you to use `--seed` to deterministically reproduce
|
83
|
+
# test failures related to randomization by passing the same `--seed` value
|
84
|
+
# as the one that triggered the failure.
|
85
|
+
Kernel.srand config.seed
|
86
|
+
=end
|
87
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
---
|
2
|
+
:determiner_common: [
|
3
|
+
[the]
|
4
|
+
]
|
5
|
+
:adjective_common: [
|
6
|
+
[red],
|
7
|
+
[orange]
|
8
|
+
]
|
9
|
+
:noun_common: [
|
10
|
+
[thing],
|
11
|
+
[zombie],
|
12
|
+
[samurai]
|
13
|
+
]
|
14
|
+
:verb_common: [
|
15
|
+
[see],
|
16
|
+
[attack],
|
17
|
+
[decipher]
|
18
|
+
]
|
19
|
+
:verb_self_common: [
|
20
|
+
[fight],
|
21
|
+
[travel],
|
22
|
+
[meditate]
|
23
|
+
]
|
metadata
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: haiku_gadget
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Scott Balay
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-09-30 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.5'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.5'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.1'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.1'
|
55
|
+
description: i know you want it / random poetic nonsense / just click a button
|
56
|
+
email:
|
57
|
+
- sbalay@gmail.com
|
58
|
+
executables: []
|
59
|
+
extensions: []
|
60
|
+
extra_rdoc_files: []
|
61
|
+
files:
|
62
|
+
- ".gitignore"
|
63
|
+
- ".rspec"
|
64
|
+
- Gemfile
|
65
|
+
- LICENSE.txt
|
66
|
+
- README.md
|
67
|
+
- Rakefile
|
68
|
+
- haiku_gadget.gemspec
|
69
|
+
- lib/assets/.keep
|
70
|
+
- lib/haiku_gadget.rb
|
71
|
+
- lib/haiku_gadget/dictionary.rb
|
72
|
+
- lib/haiku_gadget/haiku_gadget.rb
|
73
|
+
- lib/haiku_gadget/haiku_template.rb
|
74
|
+
- lib/haiku_gadget/version.rb
|
75
|
+
- lib/haiku_gadget/word_template.rb
|
76
|
+
- lib/haiku_gadget/word_type.rb
|
77
|
+
- lib/tasks/.keep
|
78
|
+
- lib/words.yml
|
79
|
+
- spec/haiku_gadget/haiku_gadget_spec.rb
|
80
|
+
- spec/rails_helper.rb
|
81
|
+
- spec/spec_helper.rb
|
82
|
+
- spec/test_words_nested.yml
|
83
|
+
- spec/test_words_single.yml
|
84
|
+
homepage: http://github.com/zenblender/haiku_gadget
|
85
|
+
licenses:
|
86
|
+
- MIT
|
87
|
+
metadata: {}
|
88
|
+
post_install_message:
|
89
|
+
rdoc_options: []
|
90
|
+
require_paths:
|
91
|
+
- lib
|
92
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
98
|
+
requirements:
|
99
|
+
- - ">="
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
requirements: []
|
103
|
+
rubyforge_project:
|
104
|
+
rubygems_version: 2.2.1
|
105
|
+
signing_key:
|
106
|
+
specification_version: 4
|
107
|
+
summary: Random haiku generator
|
108
|
+
test_files:
|
109
|
+
- spec/haiku_gadget/haiku_gadget_spec.rb
|
110
|
+
- spec/rails_helper.rb
|
111
|
+
- spec/spec_helper.rb
|
112
|
+
- spec/test_words_nested.yml
|
113
|
+
- spec/test_words_single.yml
|