improvise 0.1.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 4d23a1bbb23c53484630f7e37c9eaf98aefffef7
4
+ data.tar.gz: 8017aec4d0fa52f0dcda9a65fc8ea17e1dbb573d
5
+ SHA512:
6
+ metadata.gz: b9e9f8471cd08b819667c12dcfe45ef24ca94d2ba9f1ec9180cca1d8e3d8f4c83e6071333c2ca01c3a1b9eeaeb368d8a24a864eef9cf566c11c0bdb08121b88f
7
+ data.tar.gz: b8d199c5a1f6465e713ae5fadc6ec813cf0527ba7027c13758ce00ae6241c9631f42357b59b6aaec652543beae552a99a57cc7dd47ccd89a02acfd27dbc491db
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014 Sander Kleykens
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,115 @@
1
+ # Improvise
2
+ Improvise generates random words by learning from existing text.
3
+
4
+ ## Installation
5
+ Add this line to your application's Gemfile:
6
+
7
+ ```
8
+ gem 'improvise'
9
+ ```
10
+
11
+ And then execute:
12
+
13
+ ```
14
+ $ bundle
15
+ ```
16
+ Or install it yourself as:
17
+
18
+ ```
19
+ $ gem install improvise
20
+ ```
21
+
22
+ ## Usage
23
+ Require the 'improvise' gem:
24
+
25
+ ```ruby
26
+ require 'improvise'
27
+ ```
28
+
29
+ ### Learn
30
+ Create a new dictionary with depth 3 and learn from a list of existing words:
31
+
32
+ ```ruby
33
+ dict = Improvise::ForwardDictionary.new(3)
34
+ dict.learn!([
35
+ 'ruby',
36
+ 'sapphire',
37
+ 'pearl',
38
+ 'diamond',
39
+ 'amethyst',
40
+ 'topaz',
41
+ 'emerald'
42
+ ])
43
+ ```
44
+
45
+ ### Generate
46
+ Generate a 6-letter word:
47
+
48
+ ```ruby
49
+ dict.generate_word(6)
50
+ ```
51
+
52
+ Generate a 7-letter word, starting with 'top':
53
+
54
+ ```ruby
55
+ dict.generate_word(7, 'top')
56
+ ```
57
+
58
+ ### Store
59
+ Write a dictionary in Ruby's Marshal format to a file called 'dict.bin':
60
+
61
+ ```ruby
62
+ dict_file = File.open('dict.bin', 'w')
63
+ Improvise::IO::DictionaryWriter.write(dict_file, dict)
64
+ ```
65
+
66
+ Write a dictionary in Ruby's Marshal format, gzipped, to a file called 'dict.bin.gz':
67
+
68
+ ```ruby
69
+ dict_file = File.open('dict.bin.gz', 'w')
70
+ Improvise::IO::DictionaryWriter.write(dict_file, dict, gzip: true)
71
+ ```
72
+
73
+ Write a dictionary in json format, gzipped, to a file called 'dict.json.gz':
74
+
75
+ ```ruby
76
+ dict_file = File.open('dict.json.gz', 'w')
77
+ Improvise::IO::DictionaryWriter.write(dict_file, dict, format: :json, gzip: true)
78
+ ```
79
+
80
+ *Note: writing a dictionary closes the passed IO object.*
81
+
82
+ ### Load
83
+ Restore a dictionary from a file called 'dict.bin' in Ruby's Marshal format:
84
+
85
+ ```ruby
86
+ dict_file = File.open('dict.bin', 'r')
87
+ dict = Improvise::IO::DictionaryReader.read(dict_file)
88
+ ```
89
+
90
+ Restore a dictionary from a file called 'dict.bin.gz' in Ruby's Marshal format, gzipped:
91
+
92
+ ```ruby
93
+ dict_file = File.open('dict.bin.gz', 'r')
94
+ dict = Improvise::IO::DictionaryReader.read(dict_file, gzip: true)
95
+ ```
96
+
97
+ Restore a dictionary from a file called 'dict.json.gz' in json format, gzipped:
98
+
99
+ ```ruby
100
+ dict_file = File.open('dict.json.gz', 'r')
101
+ dict = Improvise::IO::DictionaryReader.read(dict_file, format: :json, gzip: true)
102
+ ```
103
+
104
+ *Note: reading a dictionary closes the passed IO object.*
105
+
106
+ ## Command-line tool
107
+ A command-line interface to the library has been provided under the name 'improvise'.
108
+ Run `improvise --help` to get a list of available commands.
109
+
110
+ ## Contributing
111
+ 1. Fork
112
+ 2. Branch (`git checkout -b my-new-feature`)
113
+ 3. Commit (`git commit -am 'Added some feature'`)
114
+ 4. Push (`git push origin my-new-feature`)
115
+ 5. Pull request
data/Rakefile ADDED
@@ -0,0 +1,129 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'date'
4
+
5
+ #############################################################################
6
+ #
7
+ # Helper functions
8
+ #
9
+ #############################################################################
10
+
11
+ def name
12
+ @name ||= Dir['*.gemspec'].first.split('.').first
13
+ end
14
+
15
+ def version
16
+ line = File.read("lib/#{name}/version.rb")[/^\s*VERSION\s*=\s*.*/]
17
+ line.match(/.*VERSION\s*=\s*['"](.*)['"]/)[1]
18
+ end
19
+
20
+ def date
21
+ Date.today.to_s
22
+ end
23
+
24
+ def gemspec_file
25
+ "#{name}.gemspec"
26
+ end
27
+
28
+ def gem_file
29
+ "#{name}-#{version}.gem"
30
+ end
31
+
32
+ def replace_header(head, header_name)
33
+ head.sub!(/(\.#{header_name}\s*= ').*'/) { "#{$1}#{send(header_name)}'"}
34
+ end
35
+
36
+ #############################################################################
37
+ #
38
+ # Standard tasks
39
+ #
40
+ #############################################################################
41
+
42
+ task :default => :spec
43
+
44
+ require 'rspec/core/rake_task'
45
+ desc 'Tests'
46
+ RSpec::Core::RakeTask.new(:spec) do |test|
47
+ test.pattern = 'spec/**/*_spec.rb'
48
+ end
49
+
50
+ RSpec::Core::RakeTask.new(:coverage) do |test|
51
+ ENV['COVERAGE'] = 'true'
52
+ Rake::Task[:spec].execute
53
+ end
54
+
55
+ require 'yard'
56
+ YARD::Rake::YardocTask.new do |yard|
57
+ yard.files = ['README*', 'lib/**/*.rb']
58
+ end
59
+
60
+ desc "Open an irb session preloaded with this library"
61
+ task :console do
62
+ sh "irb -rubygems -r ./lib/#{name}.rb"
63
+ end
64
+
65
+ #############################################################################
66
+ #
67
+ # Packaging tasks
68
+ #
69
+ #############################################################################
70
+
71
+ desc "Create tag v#{version} and build and push #{gem_file} to Rubygems"
72
+ task :release => :build do
73
+ unless `git branch` =~ /^\* master$/
74
+ puts "You must be on the master branch to release!"
75
+ exit!
76
+ end
77
+ sh "git commit --allow-empty -a -m 'Release #{version}'"
78
+ sh "git tag v#{version}"
79
+ sh "git push origin master"
80
+ sh "git push origin v#{version}"
81
+ sh "gem push pkg/#{name}-#{version}.gem"
82
+ end
83
+
84
+ desc "Build #{gem_file} into the pkg directory"
85
+ task :build => :gemspec do
86
+ sh "mkdir -p pkg"
87
+ sh "gem build #{gemspec_file}"
88
+ sh "mv #{gem_file} pkg"
89
+ end
90
+
91
+ desc "Generate #{gemspec_file}"
92
+ task :gemspec => :validate do
93
+ # read spec file and split out manifest section
94
+ spec = File.read(gemspec_file)
95
+ head, manifest, tail = spec.split(" # = MANIFEST =\n")
96
+
97
+ # replace name version and date
98
+ replace_header(head, :name)
99
+ replace_header(head, :version)
100
+ replace_header(head, :date)
101
+
102
+ # determine file list from git ls-files
103
+ files = `git ls-files`.
104
+ split("\n").
105
+ sort.
106
+ reject { |file| file =~ /^\./ }.
107
+ reject { |file| file =~ /^(rdoc|pkg)/ }.
108
+ map { |file| " #{file}" }.
109
+ join("\n")
110
+
111
+ # piece file back together and write
112
+ manifest = " s.files = %w[\n#{files}\n ]\n"
113
+ spec = [head, manifest, tail].join(" # = MANIFEST =\n")
114
+ File.open(gemspec_file, 'w') { |io| io.write(spec) }
115
+ puts "Updated #{gemspec_file}"
116
+ end
117
+
118
+ desc "Validate #{gemspec_file}"
119
+ task :validate do
120
+ libfiles = Dir['lib/*'] - ["lib/#{name}.rb", "lib/#{name}"]
121
+ unless libfiles.empty?
122
+ puts "Directory `lib` should only contain a `#{name}.rb` file and `#{name}` dir."
123
+ exit!
124
+ end
125
+ unless Dir['VERSION*'].empty?
126
+ puts "A `VERSION` file at root level violates Gem best practices."
127
+ exit!
128
+ end
129
+ end
data/bin/improvise ADDED
@@ -0,0 +1,79 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'gli'
4
+ require 'json'
5
+ require 'zlib'
6
+ require 'improvise'
7
+
8
+ include GLI::App
9
+
10
+ program_desc 'Improvise generates random words by learning from existing text.'
11
+ version Improvise::VERSION
12
+
13
+ flag [:f, :format], :desc => 'The format of the dictionary (marshal or json)', :default_value => :marshal, :must_match => [ :marshal, :json ]
14
+ switch [:g, :gzip], :desc => 'Indicates if the dictionary is in gzip format', :negatable => false
15
+
16
+ desc 'Create or update a dictionary based on an input file'
17
+ arg_name 'input dictionary'
18
+ command :learn do |c|
19
+ c.flag [:d, :depth], :desc => 'The depth to use when building the dictionary', :default_value => 2, :type => Integer
20
+
21
+ c.action do |global_options, options, args|
22
+ if args.length < 1
23
+ help_now!('Input argument missing.')
24
+ elsif args.length < 2
25
+ help_now!('Dictionary argument missing.')
26
+ end
27
+
28
+ input_filename = args[0]
29
+ dictionary_filename = args[1]
30
+ depth = options[:depth]
31
+ format = global_options[:format]
32
+ gzip = global_options[:gzip]
33
+
34
+ input_file = File.open(input_filename, 'r')
35
+ words = input_file.read.split(/\W+/)
36
+ input_file.close()
37
+
38
+ if File.exists?(dictionary_filename)
39
+ dictionary = Improvise::IO::DictionaryReader.read(File.open(dictionary_filename, 'r'), format: format, gzip: gzip)
40
+ else
41
+ dictionary = Improvise::ForwardDictionary.new(depth)
42
+ end
43
+
44
+ dictionary.learn!(words)
45
+ Improvise::IO::DictionaryWriter.write(File.open(dictionary_filename, 'w'), dictionary, format: format, gzip: gzip)
46
+ end
47
+ end
48
+
49
+ desc 'Generate random words based on a dictionary'
50
+ arg_name 'dictionary length'
51
+ command :generate do |c|
52
+ c.flag [:w, :words], :desc => 'The number of words to generate', :default_value => 1, :type => Integer
53
+ c.flag [:r, :root], :desc => 'Root of the generated word', :type => String
54
+
55
+ c.action do |global_options, options, args|
56
+ if args.length < 1
57
+ help_now!('Dictionary argument missing.')
58
+ elsif args.length < 2
59
+ help_now!('Length argument missing.')
60
+ end
61
+
62
+ dictionary_filename = args[0]
63
+ words = options[:words]
64
+ root = options[:root]
65
+ format = global_options[:format]
66
+ gzip = global_options[:gzip]
67
+
68
+ begin
69
+ length = Integer(args[1])
70
+ rescue ArgumentError
71
+ exit_now!('Length argument is not an integer.')
72
+ end
73
+
74
+ dictionary = Improvise::IO::DictionaryReader.read(File.open(dictionary_filename, 'r'), format: format, gzip: gzip)
75
+ words.times { puts dictionary.generate_word(length, root) }
76
+ end
77
+ end
78
+
79
+ exit run(ARGV)
data/improvise.gemspec ADDED
@@ -0,0 +1,65 @@
1
+ require 'improvise/version'
2
+
3
+ Gem::Specification.new do |s|
4
+ s.specification_version = 2 if s.respond_to? :specification_version=
5
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
6
+ s.rubygems_version = '1.3.5'
7
+
8
+ s.name = 'improvise'
9
+ s.version = Improvise::VERSION
10
+ s.platform = Gem::Platform::RUBY
11
+ s.date = '2014-05-20'
12
+ s.authors = ['Sander Kleykens']
13
+ s.email = ['sander@kleykens.com']
14
+ s.homepage = 'http://github.com/SanderKleykens/improvise'
15
+ s.license = 'MIT'
16
+ s.summary = 'Generate random words.'
17
+ s.description = 'Improvise generates random words by learning from existing text.'
18
+
19
+ s.require_paths = %w[lib]
20
+
21
+ s.executables = ['improvise']
22
+
23
+ s.rdoc_options = ['--charset=UTF-8']
24
+ s.extra_rdoc_files = ['LICENSE', 'README.md']
25
+
26
+ s.add_dependency('gli', '~> 2.10')
27
+ s.add_dependency('json', '~> 1.8')
28
+ s.add_dependency('pickup', '>= 0.0.9', '< 1.0')
29
+ s.add_dependency('rubytree', '>= 0.9.3', '< 1.0')
30
+
31
+ s.add_development_dependency('rake', '~> 10.3')
32
+ s.add_development_dependency('rspec', '~> 2.0')
33
+ s.add_development_dependency('simplecov', '~> 0.8')
34
+ s.add_development_dependency('yard', '~> 0.8')
35
+
36
+ ## Leave this section as-is. It is automatically generated from the
37
+ ## contents of the Git repository via the gemspec task. DO NOT REMOVE
38
+ ## THE MANIFEST COMMENTS, they are used as delimiters by the task.
39
+ # = MANIFEST =
40
+ s.files = %w[
41
+ Gemfile
42
+ LICENSE
43
+ README.md
44
+ Rakefile
45
+ bin/improvise
46
+ improvise.gemspec
47
+ lib/improvise.rb
48
+ lib/improvise/dictionary.rb
49
+ lib/improvise/dictionarytree.rb
50
+ lib/improvise/forwarddictionary.rb
51
+ lib/improvise/io/dictionaryreader.rb
52
+ lib/improvise/io/dictionarywriter.rb
53
+ lib/improvise/io/io.rb
54
+ lib/improvise/version.rb
55
+ spec/improvise/dictionary_spec.rb
56
+ spec/improvise/dictionarytree_spec.rb
57
+ spec/improvise/forwarddictionary_spec.rb
58
+ spec/improvise/io/dictionaryreader_spec.rb
59
+ spec/improvise/io/dictionarywriter_spec.rb
60
+ spec/spec_helper.rb
61
+ ]
62
+ # = MANIFEST =
63
+
64
+ s.test_files = s.files.select { |path| path =~ /^spec\/*_spec.*\.rb/ }
65
+ end
@@ -0,0 +1,29 @@
1
+ require 'json'
2
+ require 'improvise/dictionarytree'
3
+
4
+ module Improvise
5
+ class Dictionary
6
+ attr_reader :depth
7
+
8
+ def initialize(depth=2, tree=nil)
9
+ @depth = depth
10
+ @tree = tree || DictionaryTree.new
11
+ end
12
+
13
+ def as_json(opts = {})
14
+ {
15
+ JSON.create_id => self.class.name,
16
+ 'depth' => @depth,
17
+ 'tree' => @tree.as_json
18
+ }
19
+ end
20
+
21
+ def to_json(*a)
22
+ as_json.to_json(*a)
23
+ end
24
+
25
+ def self.json_create(json_hash)
26
+ new(json_hash['depth'], json_hash['tree'])
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,70 @@
1
+ require 'json'
2
+ require 'tree'
3
+ require 'pickup'
4
+
5
+ module Improvise
6
+ class DictionaryTree
7
+ def initialize(root=nil)
8
+ @root = root || Tree::TreeNode.new('root')
9
+ end
10
+
11
+ def add_entry!(prefix, suffix)
12
+ prefix_node = DictionaryTree.add_node!(@root, prefix)
13
+ prefix_node.content += 1
14
+
15
+ suffix_node = DictionaryTree.add_node!(prefix_node, suffix)
16
+ suffix_node.content += 1
17
+ end
18
+
19
+ def random_prefix
20
+ DictionaryTree.new_pickup(@root).pick
21
+ end
22
+
23
+ def random_suffix(prefix)
24
+ if prefix.nil?
25
+ return nil
26
+ end
27
+
28
+ node = @root[prefix]
29
+
30
+ if node.nil?
31
+ return nil
32
+ else
33
+ return DictionaryTree.new_pickup(node).pick
34
+ end
35
+ end
36
+
37
+ def as_json(opts = {})
38
+ {
39
+ JSON.create_id => self.class.name,
40
+ 'root' => @root.as_json
41
+ }
42
+ end
43
+
44
+ def to_json(*a)
45
+ as_json.to_json(*a)
46
+ end
47
+
48
+ def self.json_create(json_hash)
49
+ new(json_hash['root'])
50
+ end
51
+
52
+ private
53
+ def self.add_node!(root, key)
54
+ node = root[key]
55
+
56
+ if node.nil?
57
+ node = Tree::TreeNode.new(key, 0)
58
+ root << node
59
+ end
60
+
61
+ node
62
+ end
63
+
64
+ def self.new_pickup(node)
65
+ key_func = Proc.new { |item| item.name }
66
+ weight_func = Proc.new { |item| item.content }
67
+ Pickup.new(node.children, key_func: key_func, weight_func: weight_func)
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,35 @@
1
+ require 'improvise/dictionary'
2
+
3
+ module Improvise
4
+ class ForwardDictionary < Dictionary
5
+ def initialize(depth=2, tree=nil)
6
+ super(depth, tree)
7
+ end
8
+
9
+ def generate_word(length, root=nil)
10
+ word = root || @tree.random_prefix
11
+ word = word.slice(0..(length - 1))
12
+
13
+ while word.length < length do
14
+ suffix = @tree.random_suffix(word[[-@depth, 0].max..-1])
15
+ word += suffix || @tree.random_prefix
16
+ word = word.slice(0..(length - 1))
17
+ end
18
+
19
+ word
20
+ end
21
+
22
+ def learn!(words)
23
+ [*words].each do |word|
24
+ @tree.add_entry!('', word.slice(0..(@depth - 1)))
25
+
26
+ word.split('').each_cons(@depth + 1) do |characters|
27
+ prefix = characters[0..-2].join('')
28
+ suffix = characters[-1]
29
+
30
+ @tree.add_entry!(prefix, suffix)
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,38 @@
1
+ require 'json'
2
+ require 'zlib'
3
+
4
+ module Improvise
5
+ module IO
6
+ class DictionaryReader
7
+ attr_accessor :format, :gzip
8
+
9
+ def initialize(opts={})
10
+ @format = opts[:format] || :marshal
11
+ @gzip = opts[:gzip] || false
12
+ end
13
+
14
+ def read(io)
15
+ input = nil
16
+
17
+ if @gzip
18
+ gz = Zlib::GzipReader.new(io)
19
+ input = gz.read
20
+ gz.close
21
+ else
22
+ input = io.read
23
+ io.close
24
+ end
25
+
26
+ if @format == :json
27
+ return JSON.load(input)
28
+ else
29
+ return Marshal.load(input)
30
+ end
31
+ end
32
+
33
+ def self.read(io, opts={})
34
+ DictionaryReader.new(opts).read(io)
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,38 @@
1
+ require 'json'
2
+ require 'zlib'
3
+
4
+ module Improvise
5
+ module IO
6
+ class DictionaryWriter
7
+ attr_accessor :format, :gzip
8
+
9
+ def initialize(opts={})
10
+ @format = opts[:format] || :marshal
11
+ @gzip = opts[:gzip] || false
12
+ end
13
+
14
+ def write(io, dictionary)
15
+ dictionary_serialized = nil
16
+
17
+ if @format == :json
18
+ dictionary_serialized = dictionary.to_json
19
+ else
20
+ dictionary_serialized = Marshal.dump(dictionary)
21
+ end
22
+
23
+ if @gzip
24
+ gz = Zlib::GzipWriter.new(io)
25
+ gz.write(dictionary_serialized)
26
+ gz.close
27
+ else
28
+ io.write(dictionary_serialized)
29
+ io.close
30
+ end
31
+ end
32
+
33
+ def self.write(io, dictionary, opts={})
34
+ DictionaryWriter.new(opts).write(io, dictionary)
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,2 @@
1
+ require 'improvise/io/dictionaryreader'
2
+ require 'improvise/io/dictionarywriter'
@@ -0,0 +1,3 @@
1
+ module Improvise
2
+ VERSION = '0.1.0'
3
+ end
data/lib/improvise.rb ADDED
@@ -0,0 +1,3 @@
1
+ require 'improvise/version'
2
+ require 'improvise/forwarddictionary'
3
+ require 'improvise/io/io'
@@ -0,0 +1,16 @@
1
+ require 'spec_helper'
2
+
3
+ describe Improvise::Dictionary do
4
+ before do
5
+ @dict1 = Improvise::Dictionary.new(1)
6
+ @dict2 = Improvise::Dictionary.new
7
+ end
8
+
9
+ it "should have depth 1" do
10
+ expect(@dict1.depth).to eq(1)
11
+ end
12
+
13
+ it "should have depth 2" do
14
+ expect(@dict2.depth).to eq(2)
15
+ end
16
+ end
@@ -0,0 +1,37 @@
1
+ require 'spec_helper'
2
+
3
+ describe Improvise::DictionaryTree do
4
+ PREFIX = 'te'
5
+ SUFFIX = 's'
6
+
7
+ before do
8
+ @empty_tree = Improvise::DictionaryTree.new
9
+ end
10
+
11
+ it "should return nil as random prefix if the tree is empty" do
12
+ expect(@empty_tree.random_prefix).to eq(nil)
13
+ end
14
+
15
+ it "should return nil as random suffix if the prefix hasn't been found" do
16
+ expect(@empty_tree.random_suffix('test')).to eq(nil)
17
+ end
18
+
19
+ it "should return nil as random suffix if the prefix is nil" do
20
+ expect(@empty_tree.random_suffix(nil)).to eq(nil)
21
+ end
22
+
23
+ it "should return '#{PREFIX}'" do
24
+ tree = Improvise::DictionaryTree.new
25
+ tree.add_entry!(PREFIX, SUFFIX)
26
+
27
+ expect(tree.random_prefix).to eq(PREFIX)
28
+ end
29
+
30
+ it "should return '#{SUFFIX}'" do
31
+ tree = Improvise::DictionaryTree.new
32
+ tree.add_entry!(PREFIX, SUFFIX)
33
+ tree.add_entry!('aa', 's')
34
+
35
+ expect(tree.random_suffix(PREFIX)).to eq(SUFFIX)
36
+ end
37
+ end
@@ -0,0 +1,31 @@
1
+ require 'spec_helper'
2
+
3
+ describe Improvise::ForwardDictionary do
4
+ before do
5
+ @dict1 = Improvise::ForwardDictionary.new(1)
6
+ @dict2 = Improvise::ForwardDictionary.new
7
+ end
8
+
9
+ it "should have depth 1" do
10
+ expect(@dict1.depth).to eq(1)
11
+ end
12
+
13
+ it "should have depth 2" do
14
+ expect(@dict2.depth).to eq(2)
15
+ end
16
+
17
+ it "should generate 'te' using depth 1" do
18
+ @dict1.learn!('te')
19
+ expect(@dict1.generate_word(2, 't')).to eq('te')
20
+ end
21
+
22
+ it "should generate 'te' using depth 2" do
23
+ @dict2.learn!('te')
24
+ expect(@dict2.generate_word(2)).to eq('te')
25
+ end
26
+
27
+ it "should generate 'tes' using depth 2" do
28
+ @dict2.learn!('tes')
29
+ expect(@dict2.generate_word(3, 'te')).to eq('tes')
30
+ end
31
+ end
@@ -0,0 +1,62 @@
1
+ require 'spec_helper'
2
+ require 'stringio'
3
+
4
+ describe Improvise::IO::DictionaryReader do
5
+ before do
6
+ json = '{
7
+ "json_class": "Improvise::ForwardDictionary",
8
+ "depth": 2,
9
+ "tree": {
10
+ "json_class": "Improvise::DictionaryTree",
11
+ "root": {
12
+ "name": "root",
13
+ "content": null,
14
+ "json_class": "Tree::TreeNode",
15
+ "children": [
16
+ {
17
+ "name": "",
18
+ "content": 1,
19
+ "json_class": "Tree::TreeNode",
20
+ "children": [
21
+ {
22
+ "name": "te",
23
+ "content": 1,
24
+ "json_class": "Tree::TreeNode"
25
+ }
26
+ ]
27
+ },
28
+ {
29
+ "name": "te",
30
+ "content": 1,
31
+ "json_class": "Tree::TreeNode",
32
+ "children": [
33
+ {
34
+ "name": "s",
35
+ "content": 1,
36
+ "json_class": "Tree::TreeNode"
37
+ }
38
+ ]
39
+ }
40
+ ]
41
+ }
42
+ }
43
+ }'
44
+
45
+ @json_buffer = StringIO.new(json)
46
+ @json_reader = Improvise::IO::DictionaryReader.new(format: :json)
47
+ end
48
+
49
+ it "should read json input correctly" do
50
+ dict = @json_reader.read(@json_buffer)
51
+ expect(dict).to be_a(Improvise::ForwardDictionary)
52
+ expect(dict.depth).to eq(2)
53
+ expect(dict.generate_word(3)).to eq('tes')
54
+ end
55
+
56
+ it "should read json input correctly (class method)" do
57
+ dict = Improvise::IO::DictionaryReader.read(@json_buffer, format: :json)
58
+ expect(dict).to be_a(Improvise::ForwardDictionary)
59
+ expect(dict.depth).to eq(2)
60
+ expect(dict.generate_word(3)).to eq('tes')
61
+ end
62
+ end
@@ -0,0 +1,65 @@
1
+ require 'spec_helper'
2
+ require 'stringio'
3
+
4
+ describe Improvise::IO::DictionaryWriter do
5
+ before do
6
+ @dict = Improvise::ForwardDictionary.new(1)
7
+ @dict.learn!('tes')
8
+
9
+ @JSON = '{"json_class":"Improvise::ForwardDictionary","depth":1,"tree":{"json_class":"Improvise::DictionaryTree","root":{"name":"root","content":null,"json_class":"Tree::TreeNode","children":[{"name":"","content":1,"json_class":"Tree::TreeNode","children":[{"name":"t","content":1,"json_class":"Tree::TreeNode"}]},{"name":"t","content":1,"json_class":"Tree::TreeNode","children":[{"name":"e","content":1,"json_class":"Tree::TreeNode"}]},{"name":"e","content":1,"json_class":"Tree::TreeNode","children":[{"name":"s","content":1,"json_class":"Tree::TreeNode"}]}]}}}'
10
+ @buffer = StringIO.new
11
+
12
+ @json_writer = Improvise::IO::DictionaryWriter.new(format: :json)
13
+ @json_gzip_writer = Improvise::IO::DictionaryWriter.new(format: :json, gzip: true)
14
+ @marshal_writer = Improvise::IO::DictionaryWriter.new
15
+ @marshal_gzip_writer = Improvise::IO::DictionaryWriter.new(gzip: true)
16
+ end
17
+
18
+ it "should write in json format correctly" do
19
+ @json_writer.write(@buffer, @dict)
20
+ expect(@buffer.string).to eq(@JSON)
21
+ expect(@buffer.closed?).to be true
22
+ end
23
+
24
+ it "should write in json format correctly (class method)" do
25
+ Improvise::IO::DictionaryWriter.write(@buffer, @dict, format: :json)
26
+ expect(@buffer.string).to eq(@JSON)
27
+ expect(@buffer.closed?).to be true
28
+ end
29
+
30
+ it "should write in marshal format" do
31
+ @marshal_writer.write(@buffer, @dict)
32
+ expect(@buffer.size).to be > 0
33
+ expect(@buffer.closed?).to be true
34
+ end
35
+
36
+ it "should write in marshal format (class method)" do
37
+ Improvise::IO::DictionaryWriter.write(@buffer, @dict)
38
+ expect(@buffer.size).to be > 0
39
+ expect(@buffer.closed?).to be true
40
+ end
41
+
42
+ it "should write in gzipped json format" do
43
+ @json_gzip_writer.write(@buffer, @dict)
44
+ expect(@buffer.size).to be > 0
45
+ expect(@buffer.closed?).to be true
46
+ end
47
+
48
+ it "should write in gzipped json format (class method)" do
49
+ Improvise::IO::DictionaryWriter.write(@buffer, @dict, format: :json, gzip: true)
50
+ expect(@buffer.size).to be > 0
51
+ expect(@buffer.closed?).to be true
52
+ end
53
+
54
+ it "should write in gzipped marshal format" do
55
+ @marshal_gzip_writer.write(@buffer, @dict)
56
+ expect(@buffer.size).to be > 0
57
+ expect(@buffer.closed?).to be true
58
+ end
59
+
60
+ it "should write in gzipped marshal format (class method)" do
61
+ Improvise::IO::DictionaryWriter.write(@buffer, @dict, gzip: true)
62
+ expect(@buffer.size).to be > 0
63
+ expect(@buffer.closed?).to be true
64
+ end
65
+ end
@@ -0,0 +1,12 @@
1
+ if ENV['COVERAGE']
2
+ require 'simplecov'
3
+
4
+ SimpleCov.start do
5
+ add_filter('spec')
6
+
7
+ add_group('Library', 'lib')
8
+ end
9
+ end
10
+
11
+ require 'rspec'
12
+ require 'improvise'
metadata ADDED
@@ -0,0 +1,193 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: improvise
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Sander Kleykens
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-05-20 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: gli
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.10'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.10'
27
+ - !ruby/object:Gem::Dependency
28
+ name: json
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.8'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.8'
41
+ - !ruby/object:Gem::Dependency
42
+ name: pickup
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: 0.0.9
48
+ - - "<"
49
+ - !ruby/object:Gem::Version
50
+ version: '1.0'
51
+ type: :runtime
52
+ prerelease: false
53
+ version_requirements: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: 0.0.9
58
+ - - "<"
59
+ - !ruby/object:Gem::Version
60
+ version: '1.0'
61
+ - !ruby/object:Gem::Dependency
62
+ name: rubytree
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: 0.9.3
68
+ - - "<"
69
+ - !ruby/object:Gem::Version
70
+ version: '1.0'
71
+ type: :runtime
72
+ prerelease: false
73
+ version_requirements: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: 0.9.3
78
+ - - "<"
79
+ - !ruby/object:Gem::Version
80
+ version: '1.0'
81
+ - !ruby/object:Gem::Dependency
82
+ name: rake
83
+ requirement: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - "~>"
86
+ - !ruby/object:Gem::Version
87
+ version: '10.3'
88
+ type: :development
89
+ prerelease: false
90
+ version_requirements: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - "~>"
93
+ - !ruby/object:Gem::Version
94
+ version: '10.3'
95
+ - !ruby/object:Gem::Dependency
96
+ name: rspec
97
+ requirement: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - "~>"
100
+ - !ruby/object:Gem::Version
101
+ version: '2.0'
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - "~>"
107
+ - !ruby/object:Gem::Version
108
+ version: '2.0'
109
+ - !ruby/object:Gem::Dependency
110
+ name: simplecov
111
+ requirement: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - "~>"
114
+ - !ruby/object:Gem::Version
115
+ version: '0.8'
116
+ type: :development
117
+ prerelease: false
118
+ version_requirements: !ruby/object:Gem::Requirement
119
+ requirements:
120
+ - - "~>"
121
+ - !ruby/object:Gem::Version
122
+ version: '0.8'
123
+ - !ruby/object:Gem::Dependency
124
+ name: yard
125
+ requirement: !ruby/object:Gem::Requirement
126
+ requirements:
127
+ - - "~>"
128
+ - !ruby/object:Gem::Version
129
+ version: '0.8'
130
+ type: :development
131
+ prerelease: false
132
+ version_requirements: !ruby/object:Gem::Requirement
133
+ requirements:
134
+ - - "~>"
135
+ - !ruby/object:Gem::Version
136
+ version: '0.8'
137
+ description: Improvise generates random words by learning from existing text.
138
+ email:
139
+ - sander@kleykens.com
140
+ executables:
141
+ - improvise
142
+ extensions: []
143
+ extra_rdoc_files:
144
+ - LICENSE
145
+ - README.md
146
+ files:
147
+ - Gemfile
148
+ - LICENSE
149
+ - README.md
150
+ - Rakefile
151
+ - bin/improvise
152
+ - improvise.gemspec
153
+ - lib/improvise.rb
154
+ - lib/improvise/dictionary.rb
155
+ - lib/improvise/dictionarytree.rb
156
+ - lib/improvise/forwarddictionary.rb
157
+ - lib/improvise/io/dictionaryreader.rb
158
+ - lib/improvise/io/dictionarywriter.rb
159
+ - lib/improvise/io/io.rb
160
+ - lib/improvise/version.rb
161
+ - spec/improvise/dictionary_spec.rb
162
+ - spec/improvise/dictionarytree_spec.rb
163
+ - spec/improvise/forwarddictionary_spec.rb
164
+ - spec/improvise/io/dictionaryreader_spec.rb
165
+ - spec/improvise/io/dictionarywriter_spec.rb
166
+ - spec/spec_helper.rb
167
+ homepage: http://github.com/SanderKleykens/improvise
168
+ licenses:
169
+ - MIT
170
+ metadata: {}
171
+ post_install_message:
172
+ rdoc_options:
173
+ - "--charset=UTF-8"
174
+ require_paths:
175
+ - lib
176
+ required_ruby_version: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - ">="
179
+ - !ruby/object:Gem::Version
180
+ version: '0'
181
+ required_rubygems_version: !ruby/object:Gem::Requirement
182
+ requirements:
183
+ - - ">="
184
+ - !ruby/object:Gem::Version
185
+ version: '0'
186
+ requirements: []
187
+ rubyforge_project:
188
+ rubygems_version: 2.2.2
189
+ signing_key:
190
+ specification_version: 2
191
+ summary: Generate random words.
192
+ test_files: []
193
+ has_rdoc: