rubberband_flamethrower 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/Gemfile ADDED
@@ -0,0 +1,15 @@
1
+ source "http://rubygems.org"
2
+ # Add dependencies required to use your gem here.
3
+ # Example:
4
+ # gem "activesupport", ">= 2.3.5"
5
+
6
+ gem "httparty", "~> 0.10.2"
7
+ gem "activesupport", "~> 3.2.13"
8
+
9
+ # Add dependencies to develop your gem here.
10
+ # Include everything needed to run rake, tests, features, etc.
11
+ group :development do
12
+ gem "rdoc", "~> 3.12"
13
+ gem "bundler", "~> 1.3.0"
14
+ gem "jeweler", "~> 1.8.4"
15
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,32 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ activesupport (3.2.13)
5
+ i18n (= 0.6.1)
6
+ multi_json (~> 1.0)
7
+ git (1.2.5)
8
+ httparty (0.10.2)
9
+ multi_json (~> 1.0)
10
+ multi_xml (>= 0.5.2)
11
+ i18n (0.6.1)
12
+ jeweler (1.8.4)
13
+ bundler (~> 1.0)
14
+ git (>= 1.2.5)
15
+ rake
16
+ rdoc
17
+ json (1.7.7)
18
+ multi_json (1.7.2)
19
+ multi_xml (0.5.3)
20
+ rake (10.0.4)
21
+ rdoc (3.12.2)
22
+ json (~> 1.4)
23
+
24
+ PLATFORMS
25
+ ruby
26
+
27
+ DEPENDENCIES
28
+ activesupport (~> 3.2.13)
29
+ bundler (~> 1.3.0)
30
+ httparty (~> 0.10.2)
31
+ jeweler (~> 1.8.4)
32
+ rdoc (~> 3.12)
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2013 Michael Orr
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,100 @@
1
+ = Rubberband Flamethrower
2
+
3
+ Rubberband Flamethrower is a collection of scripts for dealing with faked Elastic Search data.
4
+
5
+ This readme is mostly out of date because I am changing this code into a gem but I'm leaving it here and will edit when the gem conversion is completed.
6
+
7
+ The main script "inserter.rb" is a script for rapidly inserting test data into Elastic Search. It inserts fake "tweet" type objects into a "twitter" index on a local Elastic Search server at localhost:9200. It runs in an infinite loop until you stop it.
8
+
9
+ The script "retriever.rb" also runs in a constant loop, doing a search on the tweets type in the twitter index for all objects within the date range between 2 and 3 minutes ago and reports the number of objects found. This can be used to easily approximate the maximum speed obtainable for inserting to a local Elastic Search index for a given AWS box size.
10
+
11
+ == Pre-Requisites
12
+
13
+ This script has been written with ruby 1.9.3 in mind. It requires two gems: httparty and active_support. Httparty is used to send commands to the Elastic Search server. Active Support is used for the JSON library in core_ext.
14
+
15
+ == To run the inserter script:
16
+
17
+ The script "inserter.rb" will create and store objects with a message, username, and postDate to a local Elastic Search index called "twitter" for the type "tweet". The message is composed of 6 to 16 random words and capped at 140 characters.
18
+
19
+ cd /path/to/repository/rubberband_flamethrower
20
+ ruby inserter.rb
21
+
22
+ There are several word lists in the "words" folder which come from SCOWL http://wordlist.sourceforge.net/scowl-readme
23
+
24
+ The code uses the combination of the 10, 20, and 35 lists by default.
25
+
26
+ == To run the retriever:
27
+
28
+ The retriever script is set up to run in a continuous loop and report the number of objects inserted into Elastic Search during the specified time period. It defaults to a span of one minute (really one minute and one second) that occurred between two and three minutes ago.
29
+
30
+ cd /path/to/repository/rubberband_flamethrower
31
+ ruby retriever.rb
32
+
33
+ == Benchmarks
34
+
35
+ Running one AWS Small Instance. I installed and started Elastic Search and then cloned this project onto the box and started the script running in a screen session.
36
+
37
+ Running only the insert script during the time period being sampled by the retriever with it set to the default one minute (and one second) span.
38
+
39
+ A few samples from the run show that we are inserting anywhere from 6,000 to 13,000 documents in Elastic Search.
40
+
41
+ {"query":{"range":{"postDate":{"from":"20130401T20:50:24","to":"20130401T20:51:24"}}}}
42
+ 11325
43
+ {"query":{"range":{"postDate":{"from":"20130401T20:50:25","to":"20130401T20:51:25"}}}}
44
+ 11317
45
+ {"query":{"range":{"postDate":{"from":"20130401T21:08:01","to":"20130401T21:09:01"}}}}
46
+ 6365
47
+ {"query":{"range":{"postDate":{"from":"20130401T21:08:02","to":"20130401T21:09:02"}}}}
48
+ 6328
49
+ {"query":{"range":{"postDate":{"from":"20130401T21:12:33","to":"20130401T21:13:33"}}}}
50
+ 12689
51
+ {"query":{"range":{"postDate":{"from":"20130401T21:12:34","to":"20130401T21:13:34"}}}}
52
+ 12684
53
+
54
+ Running the insert script and retriever script during the time period being sampled by the retriever for a short period did not seem to greatly affect the number, though running the retriever for a long duration did greatly degrade the performance of the inserts and increased load average on the box.
55
+
56
+ Running the retriever on a sample period of an hour (and one second) instead of one minute (and one second) we still see a fairly large variance in the number being inserted per hour and so far have only seen it increasing in time. This is a very small sample and too brief and investigation to draw any real conclusions yet.
57
+
58
+ {"query":{"range":{"postDate":{"from":"20130401T20:18:43","to":"20130401T21:18:43"}}}}
59
+ 377978
60
+ {"query":{"range":{"postDate":{"from":"20130401T20:18:44","to":"20130401T21:18:44"}}}}
61
+ 378122
62
+ {"query":{"range":{"postDate":{"from":"20130401T20:30:59","to":"20130401T21:30:59"}}}}
63
+ 462394
64
+ {"query":{"range":{"postDate":{"from":"20130401T20:31:00","to":"20130401T21:31:00"}}}}
65
+ 462503
66
+ {"query":{"range":{"postDate":{"from":"20130401T20:34:19","to":"20130401T21:34:19"}}}}
67
+ 485449
68
+ {"query":{"range":{"postDate":{"from":"20130401T20:34:20","to":"20130401T21:34:20"}}}}
69
+ 485577
70
+ {"query":{"range":{"postDate":{"from":"20130401T20:40:10","to":"20130401T21:40:10"}}}}
71
+ 529912
72
+ {"query":{"range":{"postDate":{"from":"20130401T20:40:11","to":"20130401T21:40:11"}}}}
73
+ 529981
74
+
75
+
76
+ == Things to Look Into Or Do/Notes
77
+ - Does message length varying account for some of the variance in insert speed? How much?
78
+ - What role does the size of the pool of words used to construct the random sentences play in the time it takes to insert into the index?
79
+ - What happens when we add more nodes to the Elastic Search cluster?
80
+ - As the script runs longer and longer on the limited word set does it become increasingly faster or slower at indexing new content? To put it another way, does having a lot that already uses the same words make it faster or does it slow down because it now matches it up to that much more information.
81
+ - How realistic is it to use Elastic Search nodes in the same manner as MySQL master/slave relationships where all selects are done from other nodes and all inserts on a master? Is this just common sense good practice, why didn't I see this mentioned anywhere?
82
+ - These scripts need to be run from inside the rubberband_flamethrower directory because the script is using a relative link to the random words files.
83
+ - Rescue error -> Errno::ECONNREFUSED -> in inserter.rb and report that the server is not running or not accepting connections, check your configuration
84
+
85
+
86
+ == Contributing to rubberband_flamethrower
87
+
88
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
89
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
90
+ * Fork the project.
91
+ * Start a feature/bugfix branch.
92
+ * Commit and push until you are happy with your contribution.
93
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
94
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
95
+
96
+ == Copyright
97
+
98
+ Copyright (c) 2013 Michael Orr. See LICENSE.txt for
99
+ further details.
100
+
data/Rakefile ADDED
@@ -0,0 +1,61 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+
14
+ require 'jeweler'
15
+ Jeweler::Tasks.new do |gem|
16
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
17
+ gem.name = "rubberband_flamethrower"
18
+ gem.homepage = "http://github.com/imightbeinatree/rubberband_flamethrower"
19
+ gem.license = "MIT"
20
+ gem.summary = %Q{Rapidly Insert Fake Data into Elastic Search}
21
+ gem.description = %Q{Use to quickly fill up some indicies in Elastic Search and to retrieve statistics about insertion rates}
22
+ gem.email = "michael@cloudspace.com"
23
+ gem.authors = ["Michael Orr"]
24
+ # dependencies defined in Gemfile
25
+ end
26
+ Jeweler::RubygemsDotOrgTasks.new
27
+
28
+ require 'rake/testtask'
29
+ Rake::TestTask.new(:test) do |test|
30
+ test.libs << 'lib' << 'test'
31
+ test.pattern = 'test/**/test_*.rb'
32
+ test.verbose = true
33
+ end
34
+
35
+ #require 'rcov/rcovtask'
36
+ #Rcov::RcovTask.new do |test|
37
+ # test.libs << 'test'
38
+ # test.pattern = 'test/**/test_*.rb'
39
+ # test.verbose = true
40
+ # test.rcov_opts << '--exclude "gems/*"'
41
+ #end
42
+
43
+ task :default => :test
44
+
45
+ require 'rdoc/task'
46
+ Rake::RDocTask.new do |rdoc|
47
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
48
+
49
+ rdoc.rdoc_dir = 'rdoc'
50
+ rdoc.title = "rubberband_flamethrower #{version}"
51
+ rdoc.rdoc_files.include('README*')
52
+ rdoc.rdoc_files.include('lib/**/*.rb')
53
+ end
54
+
55
+ require File.dirname(__FILE__) + "/lib/rubberband_flamethrower"
56
+ namespace :rubberband_flamethrower do
57
+ desc "Insert fake data into Elastic Search"
58
+ task :fire do
59
+ RubberbandFlamethrower.start_insert
60
+ end
61
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,63 @@
1
+ # This class is specially designed to generate random data to be inserted into Elastic Search
2
+ # It creates a JSON object that approaxiamates data like you would fine in a tweet
3
+ # with fields for a message (max 140 characters), username, and post_date.
4
+ # The post_date format is parsable as a date object by default by Elastic Search
5
+ module RubberbandFlamethrower
6
+ class DataGenerator
7
+ attr_accessor :word_list
8
+
9
+ # the WORD_FILES constant is an array of included word files
10
+ # which will be used to create the pool of random words used for data generation.
11
+ # You can uncomment or comment particular files to change the size of the pool of words.
12
+ # Please see the README file in the words folder for more information about the lists.
13
+ WORD_FILES = [
14
+ # "/words/american-words.95",
15
+ # "/words/american-words.80",
16
+ # "/words/american-words.70",
17
+ # "/words/american-words.60",
18
+ # "/words/american-words.55",
19
+ # "/words/american-words.50",
20
+ # "/words/american-words.40",
21
+ "/words/american-words.35",
22
+ "/words/american-words.20",
23
+ "/words/american-words.10"
24
+ ]
25
+
26
+ # Will initialize the word_list variable with an array of all the words contained in the WORD_FILES array
27
+ def initialize
28
+ self.word_list = []
29
+ WORD_FILES.each do |word_file|
30
+ contents = File.read(File.dirname(__FILE__)+word_file)
31
+ self.word_list = word_list + contents.split(/\n/)
32
+ end
33
+ end
34
+
35
+ # create a message from between 6 and 16 random words that maxes at 140 characters and ends with a period
36
+ # @return [String]
37
+ def random_tweet
38
+ number_of_words = 6 + rand(10)
39
+ ((number_of_words.times.map{word_list.sample}.join(" "))[0,139])+"."
40
+ end
41
+
42
+ # create a random value to be used as a username
43
+ # the return value is one random word, only letters and numbers allowed
44
+ # @return [String]
45
+ def random_username
46
+ word_list.sample.gsub(/[^0-9a-z]/i, '')
47
+ end
48
+
49
+ # create an Elastic Search friendly timestamp for right now
50
+ # @return [String]
51
+ def current_timestamp
52
+ Time.now.strftime "%Y%m%dT%H:%M:%S"
53
+ end
54
+
55
+ # generate a JSON object that contains a message, username, and post_date
56
+ # intended to be passed as insert data to an elastic search server
57
+ # @return [JSON]
58
+ def generate_random_insert_data
59
+ {message: "#{random_tweet}", username: "#{random_username}", post_date: "#{current_timestamp}"}.to_json
60
+ end
61
+
62
+ end
63
+ end
@@ -0,0 +1,37 @@
1
+ # Rubberband Flamethrower is a collection of scripts for dealing with faked Elastic Search data.
2
+ # This file is the main script for inserting fake data
3
+ # It inserts fake "tweet" type objects into a "twitter" index
4
+ # on a local Elastic Search server at localhost:9200.
5
+ # It runs in an infinite loop until you stop it.
6
+ #
7
+ #
8
+ # Author:: Michael Orr
9
+ # email - michael@cloudspace.com
10
+ # twitter - @imbiat
11
+ # Copyright:: Copyright (c) 2013
12
+ # License:: MIT License
13
+
14
+
15
+ require_relative "data_generator.rb"
16
+
17
+ # a unique ID must be provided for each document stored in Elastic Search
18
+ # since we are looping, we set a starting id and it will be incremented in the loop
19
+ id = 2
20
+
21
+ # initialize the random data generator object
22
+ data = DataGenerator.new
23
+
24
+ # start infinite loop
25
+ while true do
26
+
27
+ # generate a piece of random data to insert that approxiamates a tweet
28
+ insert_data = data.generate_random_insert_data
29
+ puts insert_data
30
+
31
+ # insert the random data into local elastic search index "twitter" as type "tweet" with set id
32
+ response = HTTParty.put("http://localhost:9200/twitter/tweet/#{id}", body: insert_data)
33
+ puts response.body
34
+
35
+ #increment the insert id
36
+ id = id + 1
37
+ end
@@ -0,0 +1,37 @@
1
+ # Rubberband Flamethrower is a collection of scripts for dealing with faked Elastic Search data.
2
+ # This file is the main script for retrieving fake data
3
+ # When running it will loop continuously
4
+ # doing a search on the tweets type in the twitter index
5
+ # for all objects within the date range between 2 and 3 minutes ago
6
+ # and reports the number of objects found.
7
+ #
8
+ # This can be used to easily approximate the maximum speed obtainable
9
+ # for inserting to a local Elastic Search index for a given AWS box size.
10
+ #
11
+ #
12
+ # Author:: Michael Orr
13
+ # email - michael@cloudspace.com
14
+ # twitter - @imbiat
15
+ # Copyright:: Copyright (c) 2013
16
+ # License:: MIT License
17
+
18
+
19
+ require 'httparty'
20
+ require "active_support/core_ext"
21
+
22
+ # start infinite loop
23
+ while true do
24
+
25
+ # set up start and end range values for query
26
+ range_start = (Time.now - 3.minutes).strftime "%Y%m%dT%H:%M:%S"
27
+ range_end = (Time.now - 2.minutes).strftime "%Y%m%dT%H:%M:%S"
28
+
29
+ # set up json for elastic search range query
30
+ query = {query: {range: { postDate: {from: "#{range_start}", to: "#{range_end}"}}}}.to_json
31
+ puts query
32
+
33
+ # perform elastic search query and report results
34
+ response = HTTParty.get("http://localhost:9200/twitter/tweet/_search", body: query)
35
+ parsed = JSON.parse(response.body)
36
+ puts "hits found: #{parsed["hits"]["total"]}"
37
+ end
@@ -0,0 +1,48 @@
1
+ These word lists are from the SCOWL wordlist set:
2
+
3
+ http://downloads.sourceforge.net/wordlist/scowl-7.1.tar.gz
4
+ http://wordlist.sourceforge.net/scowl-readme
5
+ http://wordlist.sourceforge.net/scowl-7.1-readme
6
+
7
+ The SCOWL word lists are used primarily for spellchecking.
8
+
9
+ I use just the 10, 20, and 35 lists by default.
10
+
11
+ The following information appears in the scowl-readme file linked above.
12
+
13
+ And here is a count on the number of in each spelling category
14
+ (american + english spelling category):
15
+
16
+ Size Words Names Running Total %
17
+ 10 4,427 15 4,442 0.7
18
+ 20 8,122 0 12,564 1.9
19
+ 35 37,251 224 50,039 7.7
20
+ 40 6,802 503 57,344 8.8
21
+ 50 24,505 15,455 97,304 14.9
22
+ 55 6,555 0 103,859 15.9
23
+ 60 13,633 775 118,267 18.1
24
+ 70 35,507 7,747 161,521 24.8
25
+ 80 143,791 33,293 338,605 51.9
26
+ 95 227,056 86,814 652,475 100.0
27
+
28
+ COPYRIGHT, SOURCES, and CREDITS:
29
+
30
+ The collective work is Copyright 2000-2011 by Kevin Atkinson as well
31
+ as any of the copyrights mentioned below:
32
+
33
+ Copyright 2000-2011 by Kevin Atkinson
34
+
35
+ Permission to use, copy, modify, distribute and sell these word
36
+ lists, the associated scripts, the output created from the scripts,
37
+ and its documentation for any purpose is hereby granted without fee,
38
+ provided that the above copyright notice appears in all copies and
39
+ that both that copyright notice and this permission notice appear in
40
+ supporting documentation. Kevin Atkinson makes no representations
41
+ about the suitability of this array for any purpose. It is provided
42
+ "as is" without express or implied warranty.
43
+
44
+ Alan Beale <biljir@pobox.com> also deserves special credit as he has,
45
+ in addition to providing the 12Dicts package and being a major
46
+ contributor to the ENABLE word list, given me an incredible amount of
47
+ feedback and created a number of special lists (those found in the
48
+ Supplement) in order to help improve the overall quality of SCOWL.
@@ -0,0 +1,35 @@
1
+ afterward
2
+ among
3
+ analog
4
+ apologize
5
+ behavior
6
+ catalog
7
+ center
8
+ color
9
+ color's
10
+ colors
11
+ defense
12
+ favor
13
+ favorite
14
+ flavor
15
+ gray
16
+ judgment
17
+ labeled
18
+ labeling
19
+ labor
20
+ learned
21
+ organization
22
+ organize
23
+ organized
24
+ organizes
25
+ organizing
26
+ realize
27
+ realized
28
+ realizes
29
+ realizing
30
+ recognize
31
+ recognized
32
+ recognizes
33
+ recognizing
34
+ rumor
35
+ spelled
@@ -0,0 +1,169 @@
1
+ adapter
2
+ aging
3
+ analyze
4
+ analyzed
5
+ analyzes
6
+ analyzing
7
+ apologized
8
+ apologizes
9
+ apologizing
10
+ appall
11
+ appalls
12
+ ass
13
+ authorization
14
+ authorize
15
+ authorized
16
+ authorizes
17
+ authorizing
18
+ ax
19
+ ax's
20
+ buses
21
+ canceled
22
+ canceling
23
+ catalog's
24
+ catalogs
25
+ center's
26
+ centered
27
+ centering
28
+ centers
29
+ civilization
30
+ civilize
31
+ civilized
32
+ civilizes
33
+ civilizing
34
+ colored
35
+ coloring
36
+ computerize
37
+ computerized
38
+ computerizes
39
+ computerizing
40
+ counseled
41
+ counseling
42
+ cozy
43
+ criticize
44
+ criticized
45
+ criticizes
46
+ criticizing
47
+ dialed
48
+ dialing
49
+ dialings
50
+ dreamed
51
+ emphasize
52
+ emphasized
53
+ emphasizes
54
+ emphasizing
55
+ endeavor
56
+ favor's
57
+ favorable
58
+ favored
59
+ favoring
60
+ favorite's
61
+ favorites
62
+ favors
63
+ fiber
64
+ fiber's
65
+ fibers
66
+ finalize
67
+ finalized
68
+ finalizes
69
+ finalizing
70
+ fulfill
71
+ fulfills
72
+ generalization
73
+ generalization's
74
+ generalizations
75
+ generalize
76
+ generalized
77
+ generalizes
78
+ generalizing
79
+ honor
80
+ honor's
81
+ honored
82
+ honoring
83
+ honors
84
+ humor
85
+ initialization
86
+ initialize
87
+ initialized
88
+ initializes
89
+ initializing
90
+ inquire
91
+ inquired
92
+ inquires
93
+ inquiries
94
+ inquiring
95
+ inquiry
96
+ inquiry's
97
+ judgment's
98
+ judgments
99
+ license's
100
+ liter
101
+ marvelous
102
+ maximize
103
+ minimize
104
+ modeled
105
+ modeling
106
+ modelings
107
+ mold
108
+ neighbor
109
+ neighbor's
110
+ neighborhood
111
+ neighbors
112
+ offense
113
+ offense's
114
+ offenses
115
+ optimization
116
+ optimize
117
+ optimized
118
+ optimizes
119
+ optimizing
120
+ organization's
121
+ organizations
122
+ organizer
123
+ organizer's
124
+ organizers
125
+ patronize
126
+ patronized
127
+ patronizes
128
+ patronizing
129
+ practiced
130
+ practicing
131
+ privatization
132
+ publicize
133
+ publicized
134
+ publicizes
135
+ publicizing
136
+ realization
137
+ recognizable
138
+ rumor's
139
+ rumored
140
+ rumoring
141
+ rumors
142
+ signaled
143
+ signaling
144
+ skeptical
145
+ specialize
146
+ specialized
147
+ specializes
148
+ specializing
149
+ specialty
150
+ spoiled
151
+ standardize
152
+ standardized
153
+ standardizes
154
+ standardizing
155
+ subsidize
156
+ subsidized
157
+ subsidizes
158
+ subsidizing
159
+ summarize
160
+ summarized
161
+ summarizes
162
+ summarizing
163
+ sympathize
164
+ theater
165
+ traveled
166
+ traveling
167
+ travelings
168
+ unauthorized
169
+ whiskey