deacon 0.0.3
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 +7 -0
- data/LICENSE +625 -0
- data/README.md +131 -0
- data/Rakefile +17 -0
- data/data/gfnames.txt +256 -0
- data/data/gmnames.txt +256 -0
- data/data/srnames.txt +65536 -0
- data/lib/deacon.rb +7 -0
- data/lib/deacon/generator.rb +37 -0
- data/lib/deacon/mac_generator.rb +17 -0
- data/lib/deacon/random_generator.rb +42 -0
- data/lib/deacon/version.rb +3 -0
- data/test/test_helper.rb +2 -0
- data/test/unit/mac_generator_test.rb +33 -0
- data/test/unit/random_generator_test.rb +121 -0
- metadata +77 -0
data/lib/deacon.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
module Deacon
|
2
|
+
class Generator
|
3
|
+
DEFAULT_DATA_DIR = File.expand_path('../../../data', __FILE__)
|
4
|
+
GIVEN_MALE_NAMES_FILE = 'gmnames.txt'
|
5
|
+
GIVEN_FEMALE_NAMES_FILE = 'gfnames.txt'
|
6
|
+
SURNAMES_FILE = 'srnames.txt'
|
7
|
+
RECORD_LENGTH_GIVEN = 6
|
8
|
+
RECORD_LENGTH_SURNAME = 9
|
9
|
+
|
10
|
+
def initialize(data_dir = DEFAULT_DATA_DIR)
|
11
|
+
@data_dir = data_dir
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def data_file(filename)
|
17
|
+
File.join(@data_dir, filename)
|
18
|
+
end
|
19
|
+
|
20
|
+
def find_name(index, filename, length)
|
21
|
+
File.open(filename, 'r') do |f|
|
22
|
+
f.seek(index * length)
|
23
|
+
f.readline.chomp.strip
|
24
|
+
end
|
25
|
+
rescue Exception => e
|
26
|
+
raise "Error when seeking to #{index} in #{filename}: #{e}"
|
27
|
+
end
|
28
|
+
|
29
|
+
def mac_to_bytes(mac)
|
30
|
+
mac.split(/[:-]/).collect{|x| x.to_i(16)}
|
31
|
+
end
|
32
|
+
|
33
|
+
def mac_to_shorts(mac)
|
34
|
+
mac_to_bytes(mac).each_slice(2).collect { |a, b| (a << 8) + b }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Deacon
|
2
|
+
class MacGenerator < Generator
|
3
|
+
def generate(mac, female = false)
|
4
|
+
return [] if mac.nil? || mac.empty?
|
5
|
+
# B0 B1 B2 B3 B4 B5
|
6
|
+
# SHRT0 SHRT1 SHRT2
|
7
|
+
bytes = mac_to_bytes(mac)
|
8
|
+
shorts = mac_to_shorts(mac)
|
9
|
+
filename = (shorts[0] & 0x1) == 0 ? GIVEN_MALE_NAMES_FILE : GIVEN_FEMALE_NAMES_FILE
|
10
|
+
firstname1 = find_name(bytes[2], data_file(filename), RECORD_LENGTH_GIVEN)
|
11
|
+
firstname2 = find_name(bytes[3], data_file(filename), RECORD_LENGTH_GIVEN)
|
12
|
+
surname1 = find_name(shorts[0], data_file(SURNAMES_FILE), RECORD_LENGTH_SURNAME)
|
13
|
+
surname2 = find_name(shorts[2], data_file(SURNAMES_FILE), RECORD_LENGTH_SURNAME)
|
14
|
+
[firstname2, firstname1, surname1, surname2]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Deacon
|
2
|
+
class RandomGenerator < Generator
|
3
|
+
MASK = 0x1ffffff
|
4
|
+
|
5
|
+
# Fibonacci linear feedback shift register with x^25 + x^24 + x^23 + x^22 + 1 poly
|
6
|
+
def next_lfsr25(seed)
|
7
|
+
i = 1
|
8
|
+
i = (seed + 1) & MASK
|
9
|
+
raise ArgumentError, "Seed #{seed} out of bounds" if seed && i == 0
|
10
|
+
i = (seed + 1) & MASK while i == 0
|
11
|
+
i = (i >> 1) | ((i[0]^i[1]^i[2]^i[3]) << 0x18)
|
12
|
+
i = (i >> 1) | ((i[0]^i[1]^i[2]^i[3]) << 0x18) while i > MASK
|
13
|
+
i - 1
|
14
|
+
end
|
15
|
+
|
16
|
+
def generate(seed = Time.now.utc.to_i)
|
17
|
+
return [] if seed.nil? || seed == 0
|
18
|
+
index = seed
|
19
|
+
loop do
|
20
|
+
index = next_lfsr25(index)
|
21
|
+
break if unique?(seed, index)
|
22
|
+
end
|
23
|
+
given_file = (index & 0x1000000) == 0 ? GIVEN_MALE_NAMES_FILE : GIVEN_FEMALE_NAMES_FILE
|
24
|
+
givenname_ix = (index & 0xff0000) >> 16
|
25
|
+
surnname_ix = index & 0xffff
|
26
|
+
firstname = find_name(givenname_ix, data_file(given_file), RECORD_LENGTH_GIVEN)
|
27
|
+
surname = find_name(surnname_ix, data_file(SURNAMES_FILE), RECORD_LENGTH_SURNAME)
|
28
|
+
[index, firstname, surname]
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.random_initial_seed
|
32
|
+
rand(MASK - 2) + 1
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
# is first (or gender) and last name different from the old value?
|
38
|
+
def unique?(ix1, ix2)
|
39
|
+
(((ix1 & 0xff0000) != (ix2 & 0xff0000)) || ((ix1 & 0x1000000) != (ix2 & 0x1000000))) && ((ix1 & 0xffff) != (ix2 & 0xffff))
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class MacGeneratorTest < MiniTest::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
dir = File.expand_path('../../../data', __FILE__)
|
6
|
+
@generator = Deacon::MacGenerator.new(dir)
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_generates_empty_array_for_nil
|
10
|
+
assert_equal [], @generator.generate(nil)
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_generates_empty_array_for_empty_string
|
14
|
+
assert_equal [], @generator.generate("")
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_generates_a_male_name
|
18
|
+
assert_equal ["DEREK", "LEVI", "PRATICO", "CEDILLO"], @generator.generate("00:00:ca:fe:01:01")
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_generates_a_female_name
|
22
|
+
assert_equal ["KATHY", "ALTA", "ROMEO", "CEDILLO"], @generator.generate("00:01:ca:fe:01:01")
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_generates_same_middle_names_for_single_oid
|
26
|
+
name1 = @generator.generate("24:a4:3c:ec:76:06")
|
27
|
+
name2 = @generator.generate("24:a4:3c:e3:d3:92")
|
28
|
+
#puts name1.inspect
|
29
|
+
#puts name2.inspect
|
30
|
+
assert_equal name1[1], name2[1]
|
31
|
+
assert_equal name1[2], name2[2]
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class RandomGeneratorTest < MiniTest::Unit::TestCase
|
4
|
+
# number of test iterations for some tests
|
5
|
+
TEST_ITERATIONS=10_000
|
6
|
+
|
7
|
+
def setup
|
8
|
+
@dir = File.expand_path('../../../data', __FILE__)
|
9
|
+
@generator = Deacon::RandomGenerator.new(@dir)
|
10
|
+
@random = rand((2 ** 25) - (TEST_ITERATIONS+3))
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_generates_empty_array_for_nil
|
14
|
+
assert_equal [], @generator.generate(nil)
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_generates_a_deterministic_sequence
|
18
|
+
expected = [
|
19
|
+
[0x1000000, 'VELMA', 'PRATICO'],
|
20
|
+
[0x17fffff, 'ANGIE', 'WARMBROD'],
|
21
|
+
[0x0017fff, 'GRANT', 'GOODGINE'],
|
22
|
+
[0x000bfff, 'ALTON', 'SIEBER'],
|
23
|
+
[0x100000b, 'VELMA', 'VANBEEK'],
|
24
|
+
[0x0800005, 'DON', 'OTERO'],
|
25
|
+
[0x0400002, 'SAM', 'HULAN'],
|
26
|
+
[0x0200000, 'AARON', 'PRATICO'],
|
27
|
+
[0x10fffff, 'SALLY', 'WARMBROD'],
|
28
|
+
[0x0087fff, 'TED', 'GOODGINE'],
|
29
|
+
[0x0043fff, 'CORY', 'THURSBY'],
|
30
|
+
[0x0021fff, 'GARRY', 'HANDREN'],
|
31
|
+
[0x0010fff, 'GRANT', 'STELMAN'],
|
32
|
+
[0x00087ff, 'ALTON', 'KAWSKI'],
|
33
|
+
[0x1000043, 'VELMA', 'MIRRA'],
|
34
|
+
[0x1800021, 'SUSAN', 'DARBY'],
|
35
|
+
[0x1c00010, 'MARIA', 'BOURDON'],
|
36
|
+
[0x1e00007, 'ANNIE', 'SCHMANDT'],
|
37
|
+
[0x1f00003, 'MAYRA', 'BURNAUGH'],
|
38
|
+
[0x1f80001, 'FAYE', 'ROMEO'],
|
39
|
+
[0x1fc0000, 'OPAL', 'PRATICO'],
|
40
|
+
[0x1fdffff, 'CLARA', 'WARMBROD'],
|
41
|
+
[0x07f7fff, 'DUANE', 'GOODGINE'],
|
42
|
+
[0x03fbfff, 'ERVIN', 'SIEBER'],
|
43
|
+
[0x01fdfff, 'ELDON', 'LEYUA'],
|
44
|
+
[0x00fefff, 'GARY', 'TRASHER'],
|
45
|
+
[0x007f7ff, 'BRET', 'ONDRICK'],
|
46
|
+
[0x003fbff, 'LANCE', 'BISTER'],
|
47
|
+
[0x001fdff, 'GRANT', 'KUZIEL'],
|
48
|
+
[0x000feff, 'ALTON', 'THOMPON'],
|
49
|
+
[0x10003fb, 'VELMA', 'SWILLE'],
|
50
|
+
[0x08001fd, 'DON', 'DEBRECHT'],
|
51
|
+
[0x14000fe, 'TARA', 'VAUGHNS'],
|
52
|
+
[0x0a0007e, 'HEATH', 'RUSHTON'],
|
53
|
+
[0x050003e, 'BRUCE', 'PHEONIX'],
|
54
|
+
[0x028001e, 'KURT', 'VEAZEY'],
|
55
|
+
[0x014000e, 'DEWEY', 'MOHSENI'],
|
56
|
+
[0x00a0006, 'ELI', 'DEWEY'],
|
57
|
+
[0x1050002, 'ROSA', 'HULAN'],
|
58
|
+
[0x0828000, 'JESUS', 'PONTON'],
|
59
|
+
[0x1413fff, 'MABEL', 'THURSBY'],
|
60
|
+
[0x0a09fff, 'HEATH', 'ZEHNDER'],
|
61
|
+
[0x0504fff, 'BRUCE', 'BARTOLO'],
|
62
|
+
[0x02827ff, 'KURT', 'MCCLEE'],
|
63
|
+
[0x01413ff, 'DEWEY', 'PASKELL'],
|
64
|
+
[0x00a09ff, 'ELI', 'HASFJORD'],
|
65
|
+
[0x00504ff, 'KARL', 'ANIBAL'],
|
66
|
+
[0x002827f, 'GARRY', 'SHALA'],
|
67
|
+
[0x001413f, 'GRANT', 'HIEBER'],
|
68
|
+
[0x000a09f, 'ALTON', 'PERIGO'],
|
69
|
+
]
|
70
|
+
seq = []
|
71
|
+
ix = 1
|
72
|
+
(1..50).each do |_|
|
73
|
+
ix, first, last = tuple = @generator.generate(ix)
|
74
|
+
#puts "[0x#{sprintf("%07x", ix)}, '#{first}', '#{last}'],"
|
75
|
+
seq << tuple
|
76
|
+
end
|
77
|
+
assert_equal expected, seq
|
78
|
+
end
|
79
|
+
|
80
|
+
def test_generates_a_name_for_the_initial_round
|
81
|
+
assert_equal [16777216, "VELMA", "PRATICO"], @generator.generate(1)
|
82
|
+
end
|
83
|
+
|
84
|
+
def test_generates_a_name_for_the_last_round
|
85
|
+
assert_equal [32766, "ALTON", "MCCORY"], @generator.generate((2**25) - 2)
|
86
|
+
end
|
87
|
+
|
88
|
+
def test_generates_a_name_for_each_value_in_a_sequence
|
89
|
+
@random.step(@random + TEST_ITERATIONS, 1) do |i|
|
90
|
+
@generator.generate(i)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def test_generates_non_repeating_index_sequence
|
95
|
+
test_hash = {}
|
96
|
+
ix = 1
|
97
|
+
@random.step(@random + TEST_ITERATIONS, 1) do |i|
|
98
|
+
ix = @generator.next_lfsr25(ix)
|
99
|
+
if test_hash.include? ix
|
100
|
+
fail("Found duplicated index #{ix} (iteration #{i})")
|
101
|
+
else
|
102
|
+
test_hash[ix] = 1
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def test_never_generates_two_same_names
|
108
|
+
test_hash = {}
|
109
|
+
ix = old_ix = 1
|
110
|
+
@random.step(@random + TEST_ITERATIONS, 1) do |i|
|
111
|
+
ix, first, last = @generator.generate(ix)
|
112
|
+
hash = first + last
|
113
|
+
if test_hash.include? hash
|
114
|
+
fail("Found duplicated name #{fn} #{sn} index #{old_ix}->#{ix} (iteration #{i})")
|
115
|
+
else
|
116
|
+
test_hash[hash] = 1
|
117
|
+
end
|
118
|
+
old_ix = ix
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
metadata
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: deacon
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.3
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Lukas Zapletal
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-03-07 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rdoc
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
description: Provides human readable name using continious LFSR
|
28
|
+
email:
|
29
|
+
- lukas-x@zapletalovi.com
|
30
|
+
executables: []
|
31
|
+
extensions: []
|
32
|
+
extra_rdoc_files: []
|
33
|
+
files:
|
34
|
+
- lib/deacon/random_generator.rb
|
35
|
+
- lib/deacon/mac_generator.rb
|
36
|
+
- lib/deacon/generator.rb
|
37
|
+
- lib/deacon/version.rb
|
38
|
+
- lib/deacon.rb
|
39
|
+
- data/gmnames.txt
|
40
|
+
- data/srnames.txt
|
41
|
+
- data/gfnames.txt
|
42
|
+
- LICENSE
|
43
|
+
- Rakefile
|
44
|
+
- README.md
|
45
|
+
- test/unit/mac_generator_test.rb
|
46
|
+
- test/unit/random_generator_test.rb
|
47
|
+
- test/test_helper.rb
|
48
|
+
homepage: https://github.com/lzap/deacon
|
49
|
+
licenses:
|
50
|
+
- GPLv3
|
51
|
+
- Public domain
|
52
|
+
metadata: {}
|
53
|
+
post_install_message:
|
54
|
+
rdoc_options: []
|
55
|
+
require_paths:
|
56
|
+
- lib
|
57
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
63
|
+
requirements:
|
64
|
+
- - ">="
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '0'
|
67
|
+
requirements: []
|
68
|
+
rubyforge_project:
|
69
|
+
rubygems_version: 2.0.14
|
70
|
+
signing_key:
|
71
|
+
specification_version: 4
|
72
|
+
summary: Human readable random name generator
|
73
|
+
test_files:
|
74
|
+
- test/unit/mac_generator_test.rb
|
75
|
+
- test/unit/random_generator_test.rb
|
76
|
+
- test/test_helper.rb
|
77
|
+
has_rdoc:
|