unique_names_generator 0.1.1

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.
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module UniqueNamesGenerator
4
+ module Dictionaries
5
+ # Dictionary containing numbers
6
+ module Numbers
7
+ TERMS = (1..999).freeze
8
+
9
+ def self.list_all
10
+ TERMS.map(&:to_s)
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,97 @@
1
+ # frozen_string_literal: true
2
+
3
+ module UniqueNamesGenerator
4
+ module Dictionaries
5
+ # Dictionary containing star-wars characters
6
+ module StarWars
7
+ TERMS = [
8
+ 'Ackbar',
9
+ 'Adi Gallia',
10
+ 'Anakin Skywalker',
11
+ 'Arvel Crynyd',
12
+ 'Ayla Secura',
13
+ 'Bail Prestor Organa',
14
+ 'Barriss Offee',
15
+ 'Ben Quadinaros',
16
+ 'Beru Whitesun lars',
17
+ 'Bib Fortuna',
18
+ 'Biggs Darklighter',
19
+ 'Boba Fett',
20
+ 'Bossk',
21
+ 'C-3PO',
22
+ 'Chewbacca',
23
+ 'Cliegg Lars',
24
+ 'Cordé',
25
+ 'Darth Maul',
26
+ 'Darth Vader',
27
+ 'Dexter Jettster',
28
+ 'Dooku',
29
+ 'Dormé',
30
+ 'Dud Bolt',
31
+ 'Eeth Koth',
32
+ 'Finis Valorum',
33
+ 'Gasgano',
34
+ 'Greedo',
35
+ 'Gregar Typho',
36
+ 'Grievous',
37
+ 'Han Solo',
38
+ 'IG-88',
39
+ 'Jabba Desilijic Tiure',
40
+ 'Jango Fett',
41
+ 'Jar Jar Binks',
42
+ 'Jek Tono Porkins',
43
+ 'Jocasta Nu',
44
+ 'Ki-Adi-Mundi',
45
+ 'Kit Fisto',
46
+ 'Lama Su',
47
+ 'Lando Calrissian',
48
+ 'Leia Organa',
49
+ 'Lobot',
50
+ 'Luke Skywalker',
51
+ 'Luminara Unduli',
52
+ 'Mace Windu',
53
+ 'Mas Amedda',
54
+ 'Mon Mothma',
55
+ 'Nien Nunb',
56
+ 'Nute Gunray',
57
+ 'Obi-Wan Kenobi',
58
+ 'Owen Lars',
59
+ 'Padmé Amidala',
60
+ 'Palpatine',
61
+ 'Plo Koon',
62
+ 'Poggle the Lesser',
63
+ 'Quarsh Panaka',
64
+ 'Qui-Gon Jinn',
65
+ 'R2-D2',
66
+ 'R4-P17',
67
+ 'R5-D4',
68
+ 'Ratts Tyerel',
69
+ 'Raymus Antilles',
70
+ 'Ric Olié',
71
+ 'Roos Tarpals',
72
+ 'Rugor Nass',
73
+ 'Saesee Tiin',
74
+ 'San Hill',
75
+ 'Sebulba',
76
+ 'Shaak Ti',
77
+ 'Shmi Skywalker',
78
+ 'Sly Moore',
79
+ 'Tarfful',
80
+ 'Taun We',
81
+ 'Tion Medon',
82
+ 'Wat Tambor',
83
+ 'Watto',
84
+ 'Wedge Antilles',
85
+ 'Wicket Systri Warrick',
86
+ 'Wilhuff Tarkin',
87
+ 'Yarael Poof',
88
+ 'Yoda',
89
+ 'Zam Wesell'
90
+ ].freeze
91
+
92
+ def self.list_all
93
+ TERMS
94
+ end
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module UniqueNamesGenerator
4
+ # Generate a reproducible seed from a given string
5
+ module Seed
6
+ class << self
7
+ def generate_seed(seed)
8
+ return nil if seed.nil?
9
+
10
+ transformed_string = transform_string(seed)
11
+ seed_decimal = mulberry32(transformed_string)
12
+ remove_decimal(seed_decimal)
13
+ end
14
+
15
+ private
16
+
17
+ def transform_string(seed)
18
+ return seed if seed.is_a?(Integer)
19
+
20
+ seed += "\x00"
21
+ ascii_values = seed.bytes
22
+
23
+ joined_values = ascii_values.join
24
+ joined_values.to_i
25
+ end
26
+
27
+ def remove_decimal(seed)
28
+ (seed * 10**16).to_i
29
+ end
30
+
31
+ def mulberry32(seed)
32
+ t = (seed + 0x6d2b79f5) & 0xffffffff
33
+
34
+ t = ((t ^ (t >> 15)) * (t | 1)) & 0xffffffff
35
+ t = (t ^ (t >> 7)) & 0xffffffff
36
+ t = (t ^ (t + ((t ^ (t >> 7)) * (t | 61) & 0xffffffff))) & 0xffffffff
37
+
38
+ ((t ^ (t >> 14)) & 0xffffffff) / 4294967296.0
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module UniqueNamesGenerator
4
+ VERSION = '0.1.1'
5
+ end
@@ -0,0 +1,192 @@
1
+ # frozen_string_literal: true
2
+
3
+ # An implementation of a unique_names_generator in Ruby
4
+ # with support for PRNG/seeds
5
+
6
+ require_relative './unique_names_generator/seed'
7
+
8
+ require_relative './unique_names_generator/dictionaries/adjectives'
9
+ require_relative './unique_names_generator/dictionaries/animals'
10
+ require_relative './unique_names_generator/dictionaries/colors'
11
+ require_relative './unique_names_generator/dictionaries/languages'
12
+ require_relative './unique_names_generator/dictionaries/names'
13
+ require_relative './unique_names_generator/dictionaries/numbers'
14
+ require_relative './unique_names_generator/dictionaries/star_wars'
15
+
16
+ # UniqueNamesGenerator implementation
17
+ module UniqueNamesGenerator
18
+ module_function
19
+
20
+ def generate(dictionaries, separator: '_', style: :lowercase, seed: nil, creativity: 0)
21
+ @separator = separator
22
+ @style = style
23
+ @seed = seed
24
+ @creativity = creativity
25
+
26
+ if creativity.negative? || creativity > 10
27
+ raise ArgumentError, 'Outside creativity range. Must be between 0 and 10.'
28
+ end
29
+
30
+ generate_name(dictionaries)
31
+ end
32
+
33
+ def match_word_list(dictionary)
34
+ module_name = camelize_dictionary(dictionary)
35
+ begin
36
+ dictionary = Dictionaries.const_get(module_name)
37
+ dictionary.list_all
38
+ rescue NameError
39
+ raise_invalid_dictionary(dictionary)
40
+ end
41
+ end
42
+
43
+ def word_list(dictionary)
44
+ case dictionary
45
+ when Array
46
+ dictionary if dictionary.all? { |item| item.is_a?(String) }
47
+ when Symbol
48
+ match_word_list(dictionary)
49
+ else
50
+ raise ArgumentError, 'Dictionary contains invalid dictionary type'
51
+ end
52
+ end
53
+
54
+ def random_seeded_float
55
+ seed_value = Seed.generate_seed(@seed)
56
+
57
+ prng = @seed.nil? ? Random.new : Random.new(seed_value)
58
+ prng.rand
59
+ end
60
+
61
+ def map_dictionaries(dictionaries)
62
+ dictionaries.map { |dictionary| word_list(dictionary) }
63
+ end
64
+
65
+ def split_with_separator(word)
66
+ if @separator.nil?
67
+ word.split(/(?=[A-Z])/)
68
+ else
69
+ word.split(@separator)
70
+ end
71
+ end
72
+
73
+ def format_parts(parts)
74
+ parts.map do |part|
75
+ if part.match?(/[^a-zA-Z]/) && @style == :capital
76
+ # Preserve original capitalization for parts with non-letter characters
77
+ part
78
+ else
79
+ format_word(part, @style)
80
+ end
81
+ end.join(@separator)
82
+ end
83
+
84
+ def format_multi_word(word, original_word)
85
+ if original_word.include?(' ') || original_word.include?('-')
86
+ parts = split_with_separator(word)
87
+ format_parts(parts)
88
+ else
89
+ format_word(word, @style)
90
+ end
91
+ end
92
+
93
+ def generate_name(dictionaries)
94
+ if @creativity.nil? || @creativity.zero?
95
+ generate_name_original(dictionaries)
96
+ else
97
+ generate_name_creatively(dictionaries)
98
+ end
99
+ end
100
+
101
+ def generate_name_original(dictionaries)
102
+ map_dictionaries(dictionaries).reduce(nil) do |acc, x|
103
+ rnd = (random_seeded_float * x.length).floor
104
+ original_word = x[rnd]
105
+
106
+ output_word(acc, original_word)
107
+ end
108
+ end
109
+
110
+ def generate_name_creatively(dictionaries)
111
+ word_lists = map_dictionaries(dictionaries)
112
+
113
+ word_lists.each_with_index.reduce(nil) do |acc, (word_list, index)|
114
+ creativity = calculate_creativity(index)
115
+ rnd = (random_seeded_float * word_list.length * creativity).floor
116
+ original_word = word_list[rnd % word_list.length] # Ensure we don't go out of bounds
117
+
118
+ output_word(acc, original_word)
119
+ end
120
+ end
121
+
122
+ def output_word(acc, original_word)
123
+ word = format_with_separator(original_word)
124
+ word = format_multi_word(word, original_word)
125
+
126
+ if acc
127
+ "#{acc}#{@separator}#{word}"
128
+ else
129
+ word
130
+ end
131
+ end
132
+
133
+ def calculate_creativity(index)
134
+ if index.zero?
135
+ @creativity # Base creativity for the first dictionary
136
+ else
137
+ @creativity * (2 + index * 0.5) # Increase creativity for subsequent dictionaries
138
+ end
139
+ end
140
+
141
+ def camelize_dictionary(dictionary)
142
+ dictionary.to_s.split('_').map(&:capitalize).join
143
+ end
144
+
145
+ def raise_invalid_dictionary(dictionary)
146
+ raise ArgumentError, "Invalid dictionary: #{dictionary}"
147
+ end
148
+
149
+ def format_with_separator(word)
150
+ if @separator.nil?
151
+ # If separator is empty, just remove spaces without changing case
152
+ word.gsub(/\s+/, '')
153
+ else
154
+ # If there's a separator, use it to replace spaces
155
+ word.gsub(/\s+/, @separator)
156
+ end
157
+ end
158
+
159
+ def format_word(word, style)
160
+ case style
161
+ when :lowercase
162
+ word.downcase
163
+ when :uppercase
164
+ word.upcase
165
+ when :capital
166
+ word.capitalize
167
+ else
168
+ word
169
+ end
170
+ end
171
+
172
+ private_class_method(
173
+ *%i[
174
+ generate_name
175
+ match_word_list
176
+ word_list
177
+ random_seeded_float
178
+ map_dictionaries
179
+ camelize_dictionary
180
+ raise_invalid_dictionary
181
+ format_with_separator
182
+ format_multi_word
183
+ format_parts
184
+ format_word
185
+ split_with_separator
186
+ generate_name_original
187
+ generate_name_creatively
188
+ calculate_creativity
189
+ output_word
190
+ ]
191
+ )
192
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'lib/unique_names_generator/version'
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = 'unique_names_generator'
7
+ s.version = UniqueNamesGenerator::VERSION
8
+ s.summary = 'Ruby library for generating random and unique names'
9
+ s.description = <<~DESC
10
+ Generate random and unique names in Ruby with support for PRNG
11
+ seeded/deterministic generation using a built in collection of
12
+ dictionaries, or your own.
13
+ DESC
14
+ s.authors = ['Jon Girard']
15
+ s.email = 'jongirard03@gmail.com'
16
+ s.homepage = 'https://github.com/jongirard/unique_names_generator_ruby'
17
+ s.metadata = { 'homepage_uri' => 'https://github.com/jongirard/unique_names_generator_ruby',
18
+ 'source_code_uri' => 'https://github.com/jongirard/unique_names_generator_ruby' }
19
+ s.require_paths = ['lib']
20
+ s.license = 'MIT'
21
+ s.files = Dir.chdir(File.expand_path(__dir__)) do
22
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
23
+ end
24
+
25
+ s.required_ruby_version = '>= 2.6.0'
26
+
27
+ s.add_development_dependency 'rspec', '~> 3.0'
28
+ end
metadata ADDED
@@ -0,0 +1,81 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: unique_names_generator
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Jon Girard
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2024-07-05 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rspec
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '3.0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '3.0'
27
+ description: |
28
+ Generate random and unique names in Ruby with support for PRNG
29
+ seeded/deterministic generation using a built in collection of
30
+ dictionaries, or your own.
31
+ email: jongirard03@gmail.com
32
+ executables: []
33
+ extensions: []
34
+ extra_rdoc_files: []
35
+ files:
36
+ - ".github/workflows/ruby.yml"
37
+ - ".pryrc"
38
+ - ".rspec"
39
+ - ".rubocop.yml"
40
+ - Gemfile
41
+ - Gemfile.lock
42
+ - LICENSE
43
+ - README.md
44
+ - Rakefile
45
+ - lib/unique_names_generator.rb
46
+ - lib/unique_names_generator/dictionaries/adjectives.rb
47
+ - lib/unique_names_generator/dictionaries/animals.rb
48
+ - lib/unique_names_generator/dictionaries/colors.rb
49
+ - lib/unique_names_generator/dictionaries/languages.rb
50
+ - lib/unique_names_generator/dictionaries/names.rb
51
+ - lib/unique_names_generator/dictionaries/numbers.rb
52
+ - lib/unique_names_generator/dictionaries/star_wars.rb
53
+ - lib/unique_names_generator/seed.rb
54
+ - lib/unique_names_generator/version.rb
55
+ - unique_names_generator.gemspec
56
+ homepage: https://github.com/jongirard/unique_names_generator_ruby
57
+ licenses:
58
+ - MIT
59
+ metadata:
60
+ homepage_uri: https://github.com/jongirard/unique_names_generator_ruby
61
+ source_code_uri: https://github.com/jongirard/unique_names_generator_ruby
62
+ post_install_message:
63
+ rdoc_options: []
64
+ require_paths:
65
+ - lib
66
+ required_ruby_version: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: 2.6.0
71
+ required_rubygems_version: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ requirements: []
77
+ rubygems_version: 3.2.3
78
+ signing_key:
79
+ specification_version: 4
80
+ summary: Ruby library for generating random and unique names
81
+ test_files: []