teebo 0.0.3 → 0.0.4

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c08b25e131c864ae6ff3222cf665dc2359ad7849
4
- data.tar.gz: 7533533ef81909ca782e0d3acfb53dc616592946
3
+ metadata.gz: 4d25e0acff23d8791b96d50d72b36d326143a2c1
4
+ data.tar.gz: deb705f45ee7dfc04e34b6b6021a32640ff08c5a
5
5
  SHA512:
6
- metadata.gz: 61eff7754a95eea9831e654aeee41539062d2b3b77efbf97e684ce0f3248bb196d1a236c5593a85edb25b13873dedbf3049aeb8ab5f0a714cd613ab245e64da1
7
- data.tar.gz: 4f96222ca2bfe0dafa081e3cc34f7dfe6c6590db374fd0e82f0c8cc790ea7058d3b79feb6e8b4f410c9a2c71351428e20f6023ba3555167f40897cc31d55f615
6
+ metadata.gz: bed5a9899872dc9f634824f8614838af9b70c74e4c232041484bd40889376470e8aabadb992854d87343e632839a6c1db4b7773b21db628bfb50cab3a60fda66
7
+ data.tar.gz: c941cb7f2fc2f4cf7fc6c98b8a2d5a85a8c69aeeb26adf1d74787c914cf6ade5f6ac1e6e585798a394646837c4465ff8ac5f5776192635926517e6cf4cd4a442
@@ -0,0 +1,38 @@
1
+ ---
2
+ credit-card-issuers:
3
+ -
4
+ name: American Express
5
+ iin-prefixes:
6
+ - 34
7
+ - 37
8
+ lengths:
9
+ - 15
10
+ validation: yes
11
+ probability: .092
12
+ cvc-length: 4
13
+ -
14
+ name: Discover Card
15
+ iin-prefixes: [ 6011, 622126, 622127, 622128, 622129, 622130, 622131, 622132, 622133, 622134, 622135, 622136, 622137, 622138, 622139, 622140, 622141, 622142, 622143, 622144, 622145, 622146, 622147, 622148, 622149, 622150, 622151, 622152, 622153, 622154, 622155, 622156, 622157, 622158, 622159, 622160, 622161, 622162, 622163, 622164, 622165, 622166, 622167, 622168, 622169, 622170, 622171, 622172, 622173, 622174, 622175, 622176, 622177, 622178, 622179, 622180, 622181, 622182, 622183, 622184, 622185, 622186, 622187, 622188, 622189, 622190, 622191, 622192, 622193, 622194, 622195, 622196, 622197, 622198, 622199, 622200, 6222, 6223, 6224, 6225, 6226, 6227, 6228, 622901, 622902, 622903, 622904, 622905, 622906, 622907, 622908, 622909, 622910, 622911, 622912, 622913, 622914, 622915, 622916, 622917, 622918, 622919, 622920, 622921, 622922, 622923, 622924, 622925, 644, 645, 646, 647, 648, 649, 65 ]
16
+ lengths:
17
+ - 16
18
+ validation: yes
19
+ probability: .107
20
+ cvc-length: 3
21
+ -
22
+ name: MasterCard
23
+ iin-prefixes: [ 51, 52, 53, 54, 55 ]
24
+ lengths:
25
+ - 16
26
+ validation: yes
27
+ probability: .313
28
+ cvc-length: 3
29
+ -
30
+ name: Visa
31
+ iin-prefixes:
32
+ - 4
33
+ lengths:
34
+ - 13
35
+ - 16
36
+ validation: yes
37
+ probability: .488
38
+ cvc-length: 3
@@ -1,16 +1,18 @@
1
1
  require 'sqlite3'
2
+ require 'yaml'
3
+ require 'randexp'
2
4
 
3
5
  module Teebo
4
6
 
5
- class Base
6
-
7
+ class TeeboGenerator
7
8
  def initialize
8
- # Initialize the database
9
- @database = SQLite3::Database.new "lib/data/seed-data.db"
10
- @database.results_as_hash = true
9
+ @db_connection = Teebo::DatabaseHandler.new
10
+ @yaml_mapping = YAML::load(File.open('lib/data/en-us.yml'))
11
11
  end
12
-
13
12
  end
14
13
  end
15
14
 
15
+ require 'teebo/database_handler'
16
16
  require 'teebo/name'
17
+ require 'teebo/number'
18
+ require 'teebo/credit_card'
@@ -0,0 +1,41 @@
1
+ module Teebo
2
+ #
3
+ # Helper class for generating credit card numbers. Categorizes cards according to their card
4
+ # issuer, while attempting to maintain a realistic distribution between the issuers. Also ensures
5
+ # that the credit card numbers are actually valid.
6
+ #
7
+ class CreditCard < TeeboGenerator
8
+
9
+ def initialize
10
+ super
11
+ @cc_issuers = @yaml_mapping['credit-card-issuers']
12
+ end
13
+
14
+ #
15
+ # Returns a credit card issuer according to the likelihood that it would be seen in the wild.
16
+ #
17
+ def get_issuer
18
+ random_choice = Random.rand
19
+ full_weight = 0
20
+ @cc_issuers.each do |issuer|
21
+ full_weight += issuer['probability']
22
+ if random_choice < full_weight
23
+ return issuer
24
+ end
25
+ end
26
+ end
27
+
28
+ #
29
+ # Generates a credit card number according to the pattern specified in the 'issuer' passed in.
30
+ #
31
+ def generate_number(issuer)
32
+ # TODO: Sample according to realistic distribution - numbers w/long prefixes are prioritized too highly right now.
33
+ prefix = issuer['iin-prefixes'].sample
34
+ length = issuer['lengths'].sample
35
+ puts prefix, length
36
+ end
37
+
38
+
39
+
40
+ end
41
+ end
@@ -0,0 +1,49 @@
1
+ module Teebo
2
+ # This class facilitates the use of the database that accompanies this gem. Its primary goal is to
3
+ # simplify querying the database for required data, without having to write raw SQL statements
4
+ # throughout the codebase.
5
+ #
6
+ # Author:: Russ Taylor (mailto:russ@russt.me)
7
+ class DatabaseHandler
8
+
9
+ def initialize
10
+ @database = SQLite3::Database.new 'lib/data/seed-data.db'
11
+ @database.results_as_hash = true
12
+ end
13
+
14
+ #
15
+ # Retrieves the sum of the specified column in the database. Optionally, a 'where' clause may
16
+ # be specified to restrict the sum to rows meeting a specified condition. Note that at present,
17
+ # only where clauses with one condition and an '=' comparison are supported.
18
+ #
19
+ def get_sum(table_name, column_name, where_clause=nil)
20
+ where_statement = ''
21
+ unless where_clause.nil?
22
+ where_statement = "where #{where_clause[:column]} = '#{where_clause[:condition]}'"
23
+ end
24
+ statement = <<-SQL
25
+ select sum(#{column_name}) from #{table_name} #{where_statement}
26
+ SQL
27
+
28
+ @database.execute(statement)[0][0]
29
+ end
30
+
31
+ #
32
+ # Retrieves the one row from the database where the specified number fits into this row's
33
+ # 'count_to' range.
34
+ #
35
+ def get_row_for_count(table_name, count_column, count_value, where_clause=nil)
36
+ where_statement = ''
37
+ unless where_clause.nil?
38
+ where_statement = "and #{where_clause[:column]} = '#{where_clause[:condition]}'"
39
+ end
40
+ statement = <<-SQL
41
+ select * from #{table_name} where (#{count_column} - #{count_value}) >= 0
42
+ #{where_statement}
43
+ order by id limit 1
44
+ SQL
45
+
46
+ @database.execute(statement)[0]
47
+ end
48
+ end
49
+ end
@@ -3,17 +3,20 @@ module Teebo
3
3
  # Generates names in accordance with their frequency in the United States
4
4
  # population.
5
5
  #
6
- class Name < Base
6
+ class Name < TeeboGenerator
7
+
8
+ GIVEN_NAMES_TABLE = 'given_names'
9
+ SURNAMES_TABLE = 'surnames'
7
10
 
8
11
  #
9
12
  # Picks a random first & last name, selecting a random gender if it's not
10
13
  # specified.
11
14
  #
12
- def name sex=nil
15
+ def name (sex=nil)
13
16
  if sex.nil?
14
- sex = ['M', 'F'].sample
17
+ sex = %w(M F).sample
15
18
  end
16
- given_name(sex) + " " + surname
19
+ given_name(sex) + ' ' + surname
17
20
  end
18
21
 
19
22
  #
@@ -23,52 +26,38 @@ module Teebo
23
26
  # simply be another given name of the same gender is almost certainly less
24
27
  # than 100%.
25
28
  #
26
- # TODO: Make this take into account different probablities of different
27
- # types of middle names.
28
- #
29
- def full_name sex=nil
29
+ def full_name(sex=nil)
30
+ # TODO: Take into account different probabilities of different types of middle names.
30
31
  if sex.nil?
31
- sex = ['M', 'F'].sample
32
+ sex = %w(M F).sample
32
33
  end
33
- given_name(sex) + " " + given_name(sex) + " " + surname
34
+ given_name(sex) + ' ' + given_name(sex) + ' ' + surname
34
35
  end
35
36
 
36
37
  #
37
38
  # Finds the total count for the number of names in the database.
38
39
  #
39
- def sum_count sex
40
- find_count = <<-SQL
41
- select sum(count) from 'given_names' where sex = ?
42
- SQL
43
- @database.execute(find_count, sex)[0][0]
40
+ def sum_count(sex)
41
+ @db_connection.get_sum(GIVEN_NAMES_TABLE, 'count', {column: 'sex', condition: sex})
44
42
  end
45
43
 
46
44
  #
47
45
  # Selects a random (weighted) given name from the database.
48
46
  #
49
- def given_name sex
50
- find_range_query = <<-SQL
51
- select * from given_names where sex = ?
52
- and (count_to - ?) >= 0
53
- order by id limit 1
54
- SQL
55
-
56
- count = sum_count sex
47
+ def given_name(sex)
48
+ count = sum_count(sex)
57
49
  selection = rand(count)
58
- @database.execute(find_range_query, sex, selection)[0]['name']
50
+ @db_connection.get_row_for_count(GIVEN_NAMES_TABLE, 'count_to', selection,
51
+ {column: 'sex', condition: sex})['name']
59
52
  end
60
53
 
61
54
  #
62
55
  # Selects a random (weighted) surname from the database.
63
56
  #
64
57
  def surname
65
- find_range_query = <<-SQL
66
- select * from surnames where (count_to - ?) >= 0 order by id limit 1
67
- SQL
68
-
69
- count = @database.execute('select sum(count) from surnames')[0][0]
58
+ count = @db_connection.get_sum(SURNAMES_TABLE, 'count')
70
59
  selection = rand(count)
71
- @database.execute(find_range_query, selection)[0]['name']
60
+ @db_connection.get_row_for_count(SURNAMES_TABLE, 'count_to', selection)['name']
72
61
  end
73
62
  end
74
63
  end
@@ -0,0 +1,28 @@
1
+ module Teebo
2
+ #
3
+ # Helper for generating numbers according to various distributions.
4
+ #
5
+ class Number
6
+ #
7
+ # Generates a number using a normal distribution.
8
+ #
9
+ # A basic implementation of the Box-Muller transform. Adapted from an answer by antonakos on
10
+ # Stack Overflow here: http://stackoverflow.com/questions/5825680
11
+ #
12
+ def normal_dist(mean, std_deviation, rand = lambda { Kernel.rand })
13
+ theta = 2 * Math::PI * rand.call
14
+ rho = Math.sqrt(-2 * Math.log(1 - rand.call))
15
+ scale = std_deviation * rho
16
+ mean + scale * Math.cos(theta)
17
+ end
18
+
19
+ #
20
+ # Generates a number according to Benford's law, meaning that it is more indicative of numbers
21
+ # encountered in real life.
22
+ #
23
+ def benford_dist(upper_bound, decimals=0)
24
+ (upper_bound**Random.rand).round(decimals)
25
+ end
26
+
27
+ end
28
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: teebo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Russ Taylor
@@ -30,15 +30,33 @@ dependencies:
30
30
  - - ">="
31
31
  - !ruby/object:Gem::Version
32
32
  version: 1.3.9
33
+ - !ruby/object:Gem::Dependency
34
+ name: randexp
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: 0.1.7
40
+ type: :runtime
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: 0.1.7
33
47
  description: Contains basic functionality for data generation.
34
48
  email: russ@russt.me
35
49
  executables: []
36
50
  extensions: []
37
51
  extra_rdoc_files: []
38
52
  files:
53
+ - lib/data/en-us.yml
39
54
  - lib/data/seed-data.db
40
55
  - lib/teebo.rb
56
+ - lib/teebo/credit_card.rb
57
+ - lib/teebo/database_handler.rb
41
58
  - lib/teebo/name.rb
59
+ - lib/teebo/number.rb
42
60
  homepage: http://github.com/russtaylor/teebo
43
61
  licenses:
44
62
  - MIT