improvise 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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: