spicy-proton 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,103 @@
1
+ require 'yaml'
2
+ require 'bindata'
3
+ require 'seek'
4
+
5
+ module Spicy
6
+ end
7
+
8
+ module Spicy::Disk
9
+ module Files
10
+ def self.dir
11
+ @@dir ||= File.join(File.dirname(__FILE__), 'corpus')
12
+ end
13
+
14
+ def self.adjectives
15
+ @@adjectives ||= File.join(dir, 'adjectives.bin')
16
+ end
17
+
18
+ def self.nouns
19
+ @@nouns ||= File.join(dir, 'nouns.bin')
20
+ end
21
+
22
+ def self.colors
23
+ @@colors ||= File.join(dir, 'colors.bin')
24
+ end
25
+ end
26
+
27
+ class Header < BinData::Record
28
+ endian :little
29
+ uint8 :width
30
+ uint8 :min_length
31
+ uint8 :group_count, :value => lambda { cumulative.length }
32
+ array :cumulative, :type => :uint32, :initial_length => :group_count
33
+ end
34
+
35
+ class WordList
36
+ include Spicy::Seek
37
+
38
+ def initialize(file_name)
39
+ @file = File.open(file_name, 'r')
40
+ header = Header.read(@file)
41
+ @origin = @file.pos
42
+
43
+ @width = header.width.to_i
44
+ @min = header.min_length.to_i
45
+ @max = @min + header.cumulative.count - 1
46
+
47
+ @cumulative = Hash[(@min..@max).zip(header.cumulative.to_a.map(&:to_i))]
48
+ end
49
+
50
+ def close
51
+ @file.close
52
+ end
53
+
54
+ def word(*args)
55
+ self.seek(*args) do |index, _|
56
+ @file.seek(@origin + index * @width, IO::SEEK_SET)
57
+ @file.read(@width).strip
58
+ end
59
+ end
60
+ end
61
+
62
+ class Corpus
63
+ private_class_method :new
64
+
65
+ def self.use
66
+ corpus = new
67
+ begin
68
+ yield corpus
69
+ ensure
70
+ corpus.close
71
+ end
72
+ end
73
+
74
+ def initialize
75
+ @lists = {}
76
+ end
77
+
78
+ def close
79
+ @lists.values.each(&:close)
80
+ end
81
+
82
+ def adjective(*args)
83
+ generate(:adjectives, *args)
84
+ end
85
+
86
+ def noun(*args)
87
+ generate(:nouns, *args)
88
+ end
89
+
90
+ def color(*args)
91
+ generate(:colors, *args)
92
+ end
93
+
94
+ private
95
+
96
+ def generate(type, *args)
97
+ @lists[type] ||= begin
98
+ WordList.new(Files.send(type))
99
+ end
100
+ @lists[type].word(*args)
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,71 @@
1
+ require 'yaml'
2
+ require 'seek'
3
+
4
+ module Spicy
5
+ end
6
+
7
+ module Spicy::Memory
8
+ module Files
9
+ def self.dir
10
+ @@dir ||= File.join(File.dirname(__FILE__), 'corpus')
11
+ end
12
+
13
+ def self.adjectives
14
+ @@adjectives ||= File.join(dir, 'adjectives.yaml')
15
+ end
16
+
17
+ def self.nouns
18
+ @@nouns ||= File.join(dir, 'nouns.yaml')
19
+ end
20
+
21
+ def self.colors
22
+ @@colors ||= File.join(dir, 'colors.yaml')
23
+ end
24
+ end
25
+
26
+ class WordList
27
+ include Spicy::Seek
28
+
29
+ def initialize(file_name)
30
+ dataset = YAML.load_file(file_name)
31
+
32
+ @words = dataset['words']
33
+ @cumulative = dataset['cumulative']
34
+
35
+ @min = @cumulative.keys.min
36
+ @max = @cumulative.keys.max
37
+ end
38
+
39
+ def word(*args)
40
+ self.seek(*args) do |index, length|
41
+ index -= (@cumulative[length - 1] || 0)
42
+ @words[length][index]
43
+ end
44
+ end
45
+ end
46
+
47
+ class Corpus
48
+ def initialize
49
+ dir = File.dirname(__FILE__)
50
+ @adjectives = WordList.new(Files.adjectives)
51
+ @nouns = WordList.new(Files.nouns)
52
+ @colors = WordList.new(Files.colors)
53
+ end
54
+
55
+ def adjective(*args)
56
+ @adjectives.word(*args)
57
+ end
58
+
59
+ def noun(*args)
60
+ @nouns.word(*args)
61
+ end
62
+
63
+ def color(*args)
64
+ @colors.word(*args)
65
+ end
66
+
67
+ def pair(separator = '-')
68
+ "#{self.adjective}#{separator}#{self.noun}"
69
+ end
70
+ end
71
+ end
data/lib/seek.rb ADDED
@@ -0,0 +1,30 @@
1
+ require 'securerandom'
2
+
3
+ module Spicy
4
+ module Seek
5
+ def seek(min: nil, max: nil, length: nil, &found)
6
+ if !length.nil? && (!min.nil? || !max.nil?)
7
+ raise ArgumentError.new('length cannot be specified if min or max are specified.')
8
+ end
9
+
10
+ if !min.nil? && !max.nil? && min > max
11
+ raise ArgumentError.new('min must be no more than max.')
12
+ end
13
+
14
+ min = [min || length || @min, @min].max
15
+ max = [max || length || @max, @max].min
16
+
17
+ rand_min = @cumulative[min - 1] || 0
18
+ rand_max = @cumulative[max] || @cumulative[@max]
19
+ index = SecureRandom.random_number(rand_min...rand_max)
20
+
21
+ min.upto(max) do |len|
22
+ if @cumulative[len] > index
23
+ return found.call(index, len)
24
+ end
25
+ end
26
+
27
+ nil
28
+ end
29
+ end
30
+ end
data/lib/spicy-proton.rb CHANGED
@@ -1,66 +1,55 @@
1
- require 'yaml'
2
- require 'binary'
3
- require 'files'
1
+ require 'forwardable'
2
+ require 'disk-corpus'
3
+ require 'memory-corpus'
4
4
 
5
5
  module Spicy
6
6
  class Proton
7
+ extend Forwardable
8
+
7
9
  def initialize
8
- dir = File.dirname(__FILE__)
9
- @adjectives = YAML.load_file(Files.adjectives)
10
- @nouns = YAML.load_file(Files.nouns)
11
- @colors = YAML.load_file(Files.colors)
10
+ @corpus = Memory::Corpus.new
12
11
  end
13
12
 
14
- def self.adjective
15
- BinaryCorpus.use(&:adjective)
13
+ def self.adjective(*args)
14
+ Disk::Corpus.use do |c|
15
+ c.adjective(*args)
16
+ end
16
17
  end
17
18
 
18
- def self.noun
19
- BinaryCorpus.use(&:noun)
19
+ def self.noun(*args)
20
+ Disk::Corpus.use do |c|
21
+ c.noun(*args)
22
+ end
20
23
  end
21
24
 
22
- def self.color
23
- BinaryCorpus.use(&:color)
25
+ def self.color(*args)
26
+ Disk::Corpus.use do |c|
27
+ c.color(*args)
28
+ end
24
29
  end
25
30
 
26
31
  def self.pair(separator = '-')
27
- BinaryCorpus.use do |b|
28
- "#{b.adjective}#{separator}#{b.noun}"
32
+ Disk::Corpus.use do |c|
33
+ "#{c.adjective}#{separator}#{c.noun}"
29
34
  end
30
35
  end
31
36
 
32
37
  def self.format(format)
33
- BinaryCorpus.use do |b|
34
- self.format_with(b, format)
38
+ Disk::Corpus.use do |c|
39
+ self.format_with(c, format)
35
40
  end
36
41
  end
37
42
 
38
- def adjective
39
- random(adjectives)
40
- end
41
-
42
- def noun
43
- random(nouns)
44
- end
45
-
46
- def color
47
- random(colors)
48
- end
49
-
50
- def pair(separator = '-')
51
- "#{self.adjective}#{separator}#{self.noun}"
52
- end
53
-
54
43
  def format(format)
55
44
  self.class.format_with(self, format)
56
45
  end
57
46
 
58
- attr_accessor :adjectives, :nouns, :colors
47
+ def_delegators :@corpus, :adjective, :noun, :color, :pair, :adjectives, :nouns, :colors
59
48
 
60
49
  private
61
50
 
62
51
  def self.format_with(source, format)
63
- format.gsub(/%([anc])/) do
52
+ format.gsub(/%([anc%])/) do
64
53
  case $1
65
54
  when 'a'
66
55
  source.adjective
@@ -68,13 +57,10 @@ module Spicy
68
57
  source.noun
69
58
  when 'c'
70
59
  source.color
60
+ when '%'
61
+ '%'
71
62
  end
72
63
  end
73
64
  end
74
-
75
- def random(set)
76
- index = SecureRandom.random_number(set.count)
77
- set[index]
78
- end
79
65
  end
80
66
  end
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spicy-proton
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Schmich
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-01-29 00:00:00.000000000 Z
11
+ date: 2017-01-30 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bindata
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.3'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.3'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: minitest
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -32,12 +46,15 @@ extra_rdoc_files: []
32
46
  files:
33
47
  - LICENSE
34
48
  - README.md
35
- - lib/binary.rb
49
+ - lib/corpus/adjectives.bin
36
50
  - lib/corpus/adjectives.yaml
51
+ - lib/corpus/colors.bin
37
52
  - lib/corpus/colors.yaml
38
- - lib/corpus/combined.bin
53
+ - lib/corpus/nouns.bin
39
54
  - lib/corpus/nouns.yaml
40
- - lib/files.rb
55
+ - lib/disk-corpus.rb
56
+ - lib/memory-corpus.rb
57
+ - lib/seek.rb
41
58
  - lib/spicy-proton.rb
42
59
  homepage: https://github.com/schmich/spicy-proton
43
60
  licenses:
@@ -51,7 +68,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
51
68
  requirements:
52
69
  - - ">="
53
70
  - !ruby/object:Gem::Version
54
- version: 1.9.3
71
+ version: 2.0.0
55
72
  required_rubygems_version: !ruby/object:Gem::Requirement
56
73
  requirements:
57
74
  - - ">="
data/lib/binary.rb DELETED
@@ -1,102 +0,0 @@
1
- require 'json'
2
- require 'yaml'
3
- require 'securerandom'
4
- require 'files'
5
-
6
- module Spicy
7
- class BinaryCorpus
8
- private_class_method :new
9
-
10
- def self.use
11
- file = File.open(Files.combined, 'r')
12
- begin
13
- corpus = new(file)
14
- yield corpus
15
- ensure
16
- file.close
17
- end
18
- end
19
-
20
- def initialize(file)
21
- @file = file
22
- @meta = {}
23
- self.class.corpus.keys.each do |set|
24
- bytes = @file.read(3 * 4)
25
- start, count, size = bytes.unpack('L*')
26
- @meta[set] = {
27
- start: start,
28
- count: count,
29
- size: size
30
- }
31
- end
32
- end
33
-
34
- def self.generate
35
- dir = File.dirname(__FILE__)
36
- sources = corpus.values
37
-
38
- sets = sources.map do |source|
39
- terms = YAML.load_file(source)
40
- {
41
- terms: terms,
42
- start: 0,
43
- count: terms.count,
44
- size: terms.map(&:length).max
45
- }
46
- end
47
-
48
- start = (3 * 4) * sets.length
49
- sets.each do |set|
50
- set[:start] = start
51
- start += set[:count] * set[:size]
52
- end
53
-
54
- File.open(Files.combined, 'w+') do |f|
55
- meta = []
56
- sets.each do |set|
57
- meta << set[:start]
58
- meta << set[:count]
59
- meta << set[:size]
60
- end
61
-
62
- f.write(meta.pack('L*'))
63
-
64
- sets.each do |set|
65
- set[:terms].each do |term|
66
- padding = "\0" * (set[:size] - term.length)
67
- f.write(term + padding)
68
- end
69
- end
70
- end
71
- end
72
-
73
- def adjective
74
- read_random(:adjectives)
75
- end
76
-
77
- def noun
78
- read_random(:nouns)
79
- end
80
-
81
- def color
82
- read_random(:colors)
83
- end
84
-
85
- private
86
-
87
- def read_random(set)
88
- set = @meta[set]
89
- index = SecureRandom.random_number(set[:count])
90
- @file.seek(set[:start] + index * set[:size], IO::SEEK_SET)
91
- @file.read(set[:size]).strip
92
- end
93
-
94
- def self.corpus
95
- {
96
- adjectives: Files.adjectives,
97
- nouns: Files.nouns,
98
- colors: Files.colors
99
- }
100
- end
101
- end
102
- end