teebo 0.0.3 → 0.0.4

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