dropmire 0.0.1 → 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.
- checksums.yaml +4 -4
- data/.gitignore +4 -1
- data/README.md +48 -1
- data/config/first_initial.yml +26 -0
- data/config/first_name.yml +53 -0
- data/config/middle_initial.yml +26 -0
- data/dropmire.gemspec +1 -1
- data/lib/dropmire/ext/string.rb +5 -0
- data/lib/dropmire/identity.rb +101 -0
- data/lib/dropmire/name_encoder.rb +104 -0
- data/lib/dropmire/parser.rb +105 -8
- data/lib/dropmire/soundex.rb +66 -0
- data/lib/dropmire/version.rb +1 -1
- data/lib/dropmire.rb +2 -1
- data/spec/demo.txt +3 -1
- data/spec/identity_spec.rb +80 -0
- data/spec/name_encoder_spec.rb +168 -0
- data/spec/parser_spec.rb +97 -4
- data/spec/soundex_spec.rb +188 -0
- metadata +16 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 00aff84a94e0b3f608c8c246865fb43c2f1a6ace
|
4
|
+
data.tar.gz: 2b7661d1934070955617c298abc748296e9025c7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 29a80db72e40d488c6f3e0609b70af54251cf0a242f9754e4d617c79bc909c3c9985dd15c097836e8e1d78bd50a882cbb576cb9d3da009e5ec7780d366c8d53e
|
7
|
+
data.tar.gz: dc30a3663d0f6ca55e97b8290ce73f3a202686f5ef4228f94ee2dd95f0eac09f72cf9a9ab90788bf1d9951499740eaf72f5af98dec3efddc31821562a82d5d46
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -18,7 +18,54 @@ Or install it yourself as:
|
|
18
18
|
|
19
19
|
## Usage
|
20
20
|
|
21
|
-
|
21
|
+
Install the gem:
|
22
|
+
|
23
|
+
```bash
|
24
|
+
gem install dropmire
|
25
|
+
```
|
26
|
+
|
27
|
+
Or add to Gemfile:
|
28
|
+
|
29
|
+
```bash
|
30
|
+
gem 'dropmire'
|
31
|
+
```
|
32
|
+
|
33
|
+
Do cool stuff
|
34
|
+
|
35
|
+
```ruby
|
36
|
+
person = Dropmire::Identity.new("""Your scanned input here!""")
|
37
|
+
|
38
|
+
# use your super cool new object
|
39
|
+
person.first_name
|
40
|
+
# => 'John'
|
41
|
+
|
42
|
+
person.middle_name
|
43
|
+
# => 'Pearce'
|
44
|
+
|
45
|
+
person.last_name
|
46
|
+
# => 'Doe'
|
47
|
+
|
48
|
+
person.date_of_birth
|
49
|
+
# => '1993-06-07'
|
50
|
+
|
51
|
+
person.drivers_license_number
|
52
|
+
# => 'D21242193207'
|
53
|
+
|
54
|
+
person.drivers_license_expiration_date
|
55
|
+
# => '2015-06'
|
56
|
+
|
57
|
+
person.street
|
58
|
+
# => '1234 Main St'
|
59
|
+
|
60
|
+
person.city
|
61
|
+
# => 'Tallahassee'
|
62
|
+
|
63
|
+
person.state
|
64
|
+
# => 'State'
|
65
|
+
|
66
|
+
person.zipcode
|
67
|
+
# => '12345'
|
68
|
+
```
|
22
69
|
|
23
70
|
## Contributing
|
24
71
|
|
@@ -0,0 +1,26 @@
|
|
1
|
+
A: 0
|
2
|
+
B: 60
|
3
|
+
C: 100
|
4
|
+
D: 160
|
5
|
+
E: 200
|
6
|
+
F: 240
|
7
|
+
G: 280
|
8
|
+
H: 320
|
9
|
+
I: 400
|
10
|
+
J: 420
|
11
|
+
K: 500
|
12
|
+
L: 520
|
13
|
+
M: 540
|
14
|
+
N: 620
|
15
|
+
O: 640
|
16
|
+
P: 660
|
17
|
+
Q: 700
|
18
|
+
R: 720
|
19
|
+
S: 780
|
20
|
+
T: 800
|
21
|
+
U: 840
|
22
|
+
V: 860
|
23
|
+
W: 880
|
24
|
+
X: 940
|
25
|
+
Y: 960
|
26
|
+
Z: 980
|
@@ -0,0 +1,53 @@
|
|
1
|
+
albert: 20
|
2
|
+
alice: 20
|
3
|
+
ann: 40
|
4
|
+
anna: 40
|
5
|
+
annie: 40
|
6
|
+
arthur: 40
|
7
|
+
bernard: 80
|
8
|
+
bette: 80
|
9
|
+
bettie: 80
|
10
|
+
betty: 80
|
11
|
+
carl: 120
|
12
|
+
catherine: 120
|
13
|
+
charles: 140
|
14
|
+
dorthy: 180
|
15
|
+
edward: 220
|
16
|
+
elizabeth: 220
|
17
|
+
florence: 260
|
18
|
+
donald: 180
|
19
|
+
clara: 140
|
20
|
+
frank: 260
|
21
|
+
george: 300
|
22
|
+
grace: 300
|
23
|
+
harold: 340
|
24
|
+
harriet: 340
|
25
|
+
harry: 360
|
26
|
+
hazel: 360
|
27
|
+
helen: 380
|
28
|
+
henry: 380
|
29
|
+
james: 440
|
30
|
+
jane: 440
|
31
|
+
jayne: 440
|
32
|
+
jean: 460
|
33
|
+
joan: 480
|
34
|
+
john: 460
|
35
|
+
joseph: 480
|
36
|
+
margaret: 560
|
37
|
+
martin: 560
|
38
|
+
marvin: 580
|
39
|
+
mary: 580
|
40
|
+
melvin: 600
|
41
|
+
mildred: 600
|
42
|
+
patricia: 680
|
43
|
+
paul: 680
|
44
|
+
richard: 740
|
45
|
+
robert: 760
|
46
|
+
ruby: 740
|
47
|
+
ruth: 760
|
48
|
+
thelma: 820
|
49
|
+
thomas: 820
|
50
|
+
walter: 900
|
51
|
+
wanda: 900
|
52
|
+
william: 920
|
53
|
+
wilma: 920
|
data/dropmire.gemspec
CHANGED
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
|
|
10
10
|
spec.email = ["jacobsen.connor@gmail.com"]
|
11
11
|
spec.summary = %q{A simple way to collect data from US driver's licenses.}
|
12
12
|
spec.description = %q{A simple way to collect data from US driver's licenses with a card reader.}
|
13
|
-
spec.homepage = ""
|
13
|
+
spec.homepage = "https://github.com/connorjacobsen/dropmire"
|
14
14
|
spec.license = "Apache-2.0"
|
15
15
|
|
16
16
|
spec.files = `git ls-files -z`.split("\x0")
|
@@ -0,0 +1,101 @@
|
|
1
|
+
require 'dropmire/parser'
|
2
|
+
|
3
|
+
module Dropmire
|
4
|
+
class Identity
|
5
|
+
def initialize(text)
|
6
|
+
p = Parser.new(text)
|
7
|
+
p.parse
|
8
|
+
|
9
|
+
@attrs = p.attrs
|
10
|
+
end
|
11
|
+
|
12
|
+
# naive method approach
|
13
|
+
def address
|
14
|
+
{ street: street, city: city, state: state, zipcode: zipcode }
|
15
|
+
end
|
16
|
+
|
17
|
+
def street
|
18
|
+
attrs[:address][:street]
|
19
|
+
end
|
20
|
+
|
21
|
+
def city
|
22
|
+
attrs[:address][:city]
|
23
|
+
end
|
24
|
+
|
25
|
+
def state
|
26
|
+
attrs[:address][:state]
|
27
|
+
end
|
28
|
+
|
29
|
+
def zipcode
|
30
|
+
attrs[:address][:zipcode]
|
31
|
+
end
|
32
|
+
|
33
|
+
def names
|
34
|
+
{ first: first_name, middle: middle_name, last: last_name }
|
35
|
+
end
|
36
|
+
|
37
|
+
def first_name
|
38
|
+
attrs[:name][:first]
|
39
|
+
end
|
40
|
+
|
41
|
+
def middle_name
|
42
|
+
attrs[:name][:middle]
|
43
|
+
end
|
44
|
+
|
45
|
+
def last_name
|
46
|
+
attrs[:name][:last]
|
47
|
+
end
|
48
|
+
|
49
|
+
def drivers_license_number
|
50
|
+
attrs[:license_num]
|
51
|
+
end
|
52
|
+
|
53
|
+
def drivers_license_iin
|
54
|
+
attrs[:iin]
|
55
|
+
end
|
56
|
+
|
57
|
+
def drivers_license_class
|
58
|
+
attrs[:license_class]
|
59
|
+
end
|
60
|
+
|
61
|
+
def drivers_license_expiration_date
|
62
|
+
attrs[:expiration_date]
|
63
|
+
end
|
64
|
+
|
65
|
+
def date_of_birth
|
66
|
+
attrs[:date_of_birth]
|
67
|
+
end
|
68
|
+
|
69
|
+
# For meta attr methods later...
|
70
|
+
#
|
71
|
+
# def method_missing(method, *args, &block)
|
72
|
+
# if addr_lookup method.to_s
|
73
|
+
|
74
|
+
# else
|
75
|
+
# super
|
76
|
+
# end
|
77
|
+
# end
|
78
|
+
|
79
|
+
private
|
80
|
+
|
81
|
+
def attrs
|
82
|
+
@attrs
|
83
|
+
end
|
84
|
+
|
85
|
+
# def attr_lookup(attr)
|
86
|
+
# if attrs.has_key? attr
|
87
|
+
# elsif address_vars
|
88
|
+
# elsif name_vars
|
89
|
+
# else
|
90
|
+
# end
|
91
|
+
# end
|
92
|
+
|
93
|
+
# def address_vars
|
94
|
+
# %w(street city state zipcode)
|
95
|
+
# end
|
96
|
+
|
97
|
+
# def name_vars
|
98
|
+
# %w(first middle last first_name middle_name last_name)
|
99
|
+
# end
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module Dropmire
|
4
|
+
module NameEncoder
|
5
|
+
|
6
|
+
class << self
|
7
|
+
# :first and :middle are the first and middle names to encode.
|
8
|
+
def encode(first, middle)
|
9
|
+
raise "Cannot encode nil name" if first.nil? || middle.nil?
|
10
|
+
|
11
|
+
fcode = generate_fcode(first.downcase)
|
12
|
+
mcode = find(:middle_initials, initial(middle).upcase)
|
13
|
+
|
14
|
+
"%3d" % (fcode + mcode)
|
15
|
+
end
|
16
|
+
|
17
|
+
def generate_fcode(name)
|
18
|
+
val = find(:first_names, name.downcase)
|
19
|
+
|
20
|
+
if val.nil?
|
21
|
+
val = find(:first_initials, initial(name).upcase)
|
22
|
+
end
|
23
|
+
|
24
|
+
val
|
25
|
+
end
|
26
|
+
|
27
|
+
# get the corresponding initial for a given :name.
|
28
|
+
def initial(name)
|
29
|
+
return nil if name.nil?
|
30
|
+
name[0].downcase
|
31
|
+
end
|
32
|
+
|
33
|
+
def load(filename)
|
34
|
+
load_yaml_from(filename)
|
35
|
+
end
|
36
|
+
|
37
|
+
def first_names
|
38
|
+
@first_names ||= load_first_names
|
39
|
+
end
|
40
|
+
|
41
|
+
def first_initials
|
42
|
+
@first_initials ||= load_first_initials
|
43
|
+
end
|
44
|
+
|
45
|
+
def middle_initials
|
46
|
+
@middle_initials ||= load_middle_initials
|
47
|
+
end
|
48
|
+
|
49
|
+
# searches the desired Hash (chosen by :method) for the :key
|
50
|
+
def find(method, key)
|
51
|
+
if allowed_find_methods.include? method
|
52
|
+
self.send(method).fetch(key, nil)
|
53
|
+
else
|
54
|
+
raise "Illegal find method!"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
def allowed_find_methods
|
61
|
+
[ :first_names, :first_initials, :middle_initials ]
|
62
|
+
end
|
63
|
+
|
64
|
+
def load_first_names
|
65
|
+
@first_names = load(first_name_yaml)
|
66
|
+
end
|
67
|
+
|
68
|
+
def load_first_initials
|
69
|
+
@first_initials = load(first_initial_yaml)
|
70
|
+
end
|
71
|
+
|
72
|
+
def load_middle_initials
|
73
|
+
@middle_initials = load(middle_initial_yaml)
|
74
|
+
end
|
75
|
+
|
76
|
+
def load_yaml_from(filename)
|
77
|
+
parsed = begin
|
78
|
+
YAML.load(File.open(filename))
|
79
|
+
rescue ArgumentError => e
|
80
|
+
puts "Could not parse YAML: #{e.message}"
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# YAML file name helpers #
|
85
|
+
|
86
|
+
def yaml_dir
|
87
|
+
'config/'
|
88
|
+
end
|
89
|
+
|
90
|
+
def first_name_yaml
|
91
|
+
yaml_dir + 'first_name.yml'
|
92
|
+
end
|
93
|
+
|
94
|
+
def first_initial_yaml
|
95
|
+
yaml_dir + 'first_initial.yml'
|
96
|
+
end
|
97
|
+
|
98
|
+
def middle_initial_yaml
|
99
|
+
yaml_dir + 'middle_initial.yml'
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
end
|
data/lib/dropmire/parser.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'dropmire/ext/string'
|
2
|
+
|
1
3
|
module Dropmire
|
2
4
|
class Parser
|
3
5
|
# Public: Creates a new Dropmire::Parser.
|
@@ -13,15 +15,26 @@ module Dropmire
|
|
13
15
|
# Returns the Hash of results from the string.
|
14
16
|
def initialize(text, options = {})
|
15
17
|
@text = text
|
16
|
-
@attrs = {} # empty hash for the parsed values
|
18
|
+
@attrs = {:address=>{}} # empty hash for the parsed values
|
17
19
|
end
|
18
20
|
|
19
21
|
def attrs
|
20
22
|
@attrs
|
21
23
|
end
|
22
24
|
|
23
|
-
def
|
24
|
-
|
25
|
+
def parse
|
26
|
+
parse_methods.each do |method|
|
27
|
+
self.send method
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def parse_methods
|
32
|
+
[ :parse_address, :parse_carrot_string, :date_of_birth, :zipcode,
|
33
|
+
:license_class, :expiration_date, :parse_license_num ]
|
34
|
+
end
|
35
|
+
|
36
|
+
def address
|
37
|
+
/\A[%][a-zA-Z]*/.match(@text).to_s
|
25
38
|
end
|
26
39
|
|
27
40
|
def state(addr)
|
@@ -33,11 +46,95 @@ module Dropmire
|
|
33
46
|
addr[3..l].capitalize
|
34
47
|
end
|
35
48
|
|
49
|
+
def carrot_string
|
50
|
+
str = /\^(.*)\^/.match(@text).to_s
|
51
|
+
len = str.length-2
|
52
|
+
str[1..len].split('^')
|
53
|
+
end
|
54
|
+
|
55
|
+
def parse_carrot_string
|
56
|
+
name_string, street_string = carrot_string
|
57
|
+
names split_name(name_string)
|
58
|
+
street street_string
|
59
|
+
end
|
60
|
+
|
36
61
|
def parse_address
|
37
|
-
addr = address
|
38
|
-
@attrs[:state] = state(addr)
|
39
|
-
@attrs[:city]
|
40
|
-
|
62
|
+
addr = address
|
63
|
+
@attrs[:address][:state] = state(addr)
|
64
|
+
@attrs[:address][:city] = city(addr)
|
65
|
+
|
66
|
+
[@attrs[:address][:city], @attrs[:address][:state]]
|
67
|
+
end
|
68
|
+
|
69
|
+
def split_name(name)
|
70
|
+
name.split('$')
|
71
|
+
end
|
72
|
+
|
73
|
+
def names(names)
|
74
|
+
@attrs[:name] = {
|
75
|
+
first: names[1].capitalize,
|
76
|
+
last: names[0].capitalize,
|
77
|
+
middle: names[2].capitalize
|
78
|
+
}
|
79
|
+
end
|
80
|
+
|
81
|
+
def street(street)
|
82
|
+
ary = street.split(' ')
|
83
|
+
str = []
|
84
|
+
ary.each do |s|
|
85
|
+
str << s.capitalize
|
86
|
+
end
|
87
|
+
@attrs[:address][:street] = str.join(' ')
|
88
|
+
end
|
89
|
+
|
90
|
+
def zipcode
|
91
|
+
str = /![\s]*[0-9]*/.match(@text).to_s
|
92
|
+
zip = str[1..(str.length)].strip
|
93
|
+
@attrs[:address][:zipcode] = zip[0,5]
|
94
|
+
end
|
95
|
+
|
96
|
+
def license_class
|
97
|
+
str = /![\s]*[0-9]*[\s]*[A-Z]/.match(@text).to_s
|
98
|
+
@attrs[:license_class] = str[-1]
|
99
|
+
end
|
100
|
+
|
101
|
+
def id_string
|
102
|
+
/;[0-9]*=/.match(@text).to_s.gsub(/[;=]/, '')
|
103
|
+
end
|
104
|
+
|
105
|
+
def iin(str)
|
106
|
+
@attrs[:iin] = str[0,6]
|
107
|
+
end
|
108
|
+
|
109
|
+
def license_num(str)
|
110
|
+
num_len = str.length - 8
|
111
|
+
@attrs[:license_num] = str[6,2].to_char.upcase + str[8, num_len]
|
112
|
+
end
|
113
|
+
|
114
|
+
def parse_license_num
|
115
|
+
id_str = id_string
|
116
|
+
iin(id_str)
|
117
|
+
license_num(id_str)
|
118
|
+
end
|
119
|
+
|
120
|
+
def expiration_date
|
121
|
+
str = /=[0-9]{4}/.match(@text).to_s
|
122
|
+
@attrs[:expiration_date] = transform_date str[1,4]
|
123
|
+
end
|
124
|
+
|
125
|
+
def date_of_birth
|
126
|
+
str = /=[0-9]*/.match(@text).to_s
|
127
|
+
dob = str[5,8]
|
128
|
+
year = dob[0,4]
|
129
|
+
month = dob[4,2]
|
130
|
+
day = dob[6,2]
|
131
|
+
@attrs[:date_of_birth] = "#{year}-#{month}-#{day}"
|
132
|
+
end
|
133
|
+
|
134
|
+
def transform_date(date)
|
135
|
+
y = date[0,2]
|
136
|
+
m = date[2,2]
|
137
|
+
"20#{y}-#{m}"
|
41
138
|
end
|
42
139
|
end
|
43
|
-
end
|
140
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# Implementation of the Soundex phonetic algorithm for indexing names
|
2
|
+
# by sound, as pronounced in English.
|
3
|
+
module Dropmire
|
4
|
+
module Soundex
|
5
|
+
|
6
|
+
class << self
|
7
|
+
|
8
|
+
def soundex(str_or_arr)
|
9
|
+
case str_or_arr
|
10
|
+
when String
|
11
|
+
build_code_for(str_or_arr)
|
12
|
+
when Array
|
13
|
+
str_or_arr.collect { |str| build_code_for(str) }
|
14
|
+
else
|
15
|
+
nil
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def build_code_for(str)
|
20
|
+
str = str.upcase.gsub(/[^A-Z]/, '')
|
21
|
+
return nil if str.empty?
|
22
|
+
|
23
|
+
soundex_code = str[0]
|
24
|
+
last_code = get_code str[0]
|
25
|
+
|
26
|
+
len = str.length
|
27
|
+
str[0..len].chars.each_index do |index|
|
28
|
+
return soundex_code if soundex_code.length == 4
|
29
|
+
|
30
|
+
code = get_code str[index]
|
31
|
+
if code == '0'
|
32
|
+
unless %w(W H).include? str[index]
|
33
|
+
last_code = nil
|
34
|
+
end
|
35
|
+
elsif code != last_code
|
36
|
+
soundex_code += code
|
37
|
+
last_code = code
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
return soundex_code.ljust(4, '0')
|
42
|
+
end
|
43
|
+
|
44
|
+
def get_code(char)
|
45
|
+
case char
|
46
|
+
when 'B', 'F', 'P', 'V'
|
47
|
+
'1'
|
48
|
+
when 'C', 'G', 'J', 'K', 'Q', 'S', 'X', 'Z'
|
49
|
+
'2'
|
50
|
+
when 'D', 'T'
|
51
|
+
'3'
|
52
|
+
when 'L'
|
53
|
+
'4'
|
54
|
+
when 'M', 'N'
|
55
|
+
'5'
|
56
|
+
when 'R'
|
57
|
+
'6'
|
58
|
+
else
|
59
|
+
'0'
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
end
|
data/lib/dropmire/version.rb
CHANGED
data/lib/dropmire.rb
CHANGED
data/spec/demo.txt
CHANGED
@@ -1 +1,3 @@
|
|
1
|
-
%FLTALLAHASSEE^JACOBSEN$CONNOR$ALAN^6357 SINKOLA DR^ ?;6360101021210193207=
|
1
|
+
%FLTALLAHASSEE^JACOBSEN$CONNOR$ALAN^6357 SINKOLA DR^ ?;6360101021210193207=1506199306070=?+! 323124522 E 1602 ECCECC00000?
|
2
|
+
|
3
|
+
%CAENCINITAS^MEIER$ALAIN$PIERRE^2814 CRYSTAL RIDGE RD^?;636014064752956=190819930823?+!!92024 M602162BRNBRN I67620131125 [,/,_29’;2!?
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Dropmire::Identity do
|
4
|
+
@demo_text = """%FLTALLAHASSEE^JACOBSEN$CONNOR$ALAN^1234 MAIN ST^ ?;6360101021210193207=1506199306070=?+! 123454522 E 1602 ECCECC00000?"""
|
5
|
+
identity = Dropmire::Identity.new(@demo_text)
|
6
|
+
subject { identity }
|
7
|
+
|
8
|
+
describe "#first_name" do
|
9
|
+
it "returns correct value" do
|
10
|
+
expect(subject.first_name).to eql "Connor"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "#middle_name" do
|
15
|
+
it "returns correct value" do
|
16
|
+
expect(subject.middle_name).to eql "Alan"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "#last_name" do
|
21
|
+
it "returns correct value" do
|
22
|
+
expect(subject.last_name).to eql "Jacobsen"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "#names" do
|
27
|
+
names = {first: "Connor", middle: "Alan", last: ""}
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "#address" do
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "#city" do
|
34
|
+
it "returns correct value" do
|
35
|
+
expect(subject.city).to eql "Tallahassee"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe "#state" do
|
40
|
+
it "returns correct value" do
|
41
|
+
expect(subject.state).to eql "FL"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe "#street" do
|
46
|
+
it "returns correct value" do
|
47
|
+
expect(subject.street).to eql "1234 Main St"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe "#zipcode" do
|
52
|
+
it "returns correct value" do
|
53
|
+
expect(subject.zipcode).to eql "12345"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe "#drivers_license_number" do
|
58
|
+
it "returns correct value" do
|
59
|
+
expect(subject.drivers_license_number).to eql "J21210193207"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe "#drivers_license_iin" do
|
64
|
+
it "returns correct value" do
|
65
|
+
expect(subject.drivers_license_iin).to eql "636010"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
describe "#drivers_license_expiration_date" do
|
70
|
+
it "returns correct value" do
|
71
|
+
expect(subject.drivers_license_expiration_date).to eql "2015-06"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe "#date_of_birth" do
|
76
|
+
it "returns correct value" do
|
77
|
+
expect(subject.date_of_birth).to eql "1993-06-07"
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,168 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Dropmire::NameEncoder do
|
4
|
+
|
5
|
+
subject { Dropmire::NameEncoder }
|
6
|
+
|
7
|
+
describe "#encode" do
|
8
|
+
context "William Andrew Fakename" do
|
9
|
+
it "returns correct value" do
|
10
|
+
expect(subject.encode("William", "Andrew")).to eql "921"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
context "Connor Alan Jacobsen" do
|
15
|
+
it "returns correct value" do
|
16
|
+
expect(subject.encode("Connor", "Alan")).to eql "101"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "#generate_fcode" do
|
22
|
+
context "first name NotFound" do
|
23
|
+
it "uses first initial" do
|
24
|
+
expect(subject.generate_fcode("Connor")).to eql 100
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context "first name found" do
|
29
|
+
it "returns correct value" do
|
30
|
+
expect(subject.generate_fcode("Alice")).to eql 20
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe "#initial" do
|
36
|
+
context "when not nil" do
|
37
|
+
it "returns a single char" do
|
38
|
+
expect(subject.initial('Connor').size).to eql 1
|
39
|
+
end
|
40
|
+
|
41
|
+
it "returns the correct char" do
|
42
|
+
expect(subject.initial('Connor')).to eql 'c'
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
context "when nil" do
|
47
|
+
it "returns nil" do
|
48
|
+
expect(subject.initial(nil)).to eql nil
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe "#first_names" do
|
54
|
+
it "has class Hash" do
|
55
|
+
expect(subject.first_names.class).to eql Hash
|
56
|
+
end
|
57
|
+
|
58
|
+
it "is not empty" do
|
59
|
+
expect(subject.first_names.empty?).to eql false
|
60
|
+
end
|
61
|
+
|
62
|
+
describe "sanity check" do
|
63
|
+
context "alice" do
|
64
|
+
it "returns 20" do
|
65
|
+
expect(subject.first_names["alice"]).to eql 20
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
context "donald" do
|
70
|
+
it "returns 180" do
|
71
|
+
expect(subject.first_names["donald"]).to eql 180
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe "#first_initials" do
|
78
|
+
it "has class Hash" do
|
79
|
+
expect(subject.first_initials.class).to eql Hash
|
80
|
+
end
|
81
|
+
|
82
|
+
it "is not empty" do
|
83
|
+
expect(subject.first_initials.empty?).to eql false
|
84
|
+
end
|
85
|
+
|
86
|
+
describe "sanity check" do
|
87
|
+
context "C" do
|
88
|
+
it "returns 100" do
|
89
|
+
expect(subject.first_initials["C"]).to eql 100
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
context "J" do
|
94
|
+
it "returns 420" do
|
95
|
+
expect(subject.first_initials["J"]).to eql 420
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
describe "#middle_initials" do
|
102
|
+
it "has class Hash" do
|
103
|
+
expect(subject.middle_initials.class).to eql Hash
|
104
|
+
end
|
105
|
+
|
106
|
+
it "is not empty" do
|
107
|
+
expect(subject.middle_initials.empty?).to eql false
|
108
|
+
end
|
109
|
+
|
110
|
+
describe "sanity check" do
|
111
|
+
context "C" do
|
112
|
+
it "returns 3" do
|
113
|
+
expect(subject.middle_initials["C"]).to eql 3
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
context "J" do
|
118
|
+
it "returns 10" do
|
119
|
+
expect(subject.middle_initials["J"]).to eql 10
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
describe "#find" do
|
126
|
+
context "first_names" do
|
127
|
+
context "when in YAML" do
|
128
|
+
it "returns correct value" do
|
129
|
+
expect(subject.find(:first_names, "donald")).to eql 180
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
context "when not in YAML" do
|
134
|
+
it "returns nil" do
|
135
|
+
expect(subject.find(:first_names, "connor")).to eql nil
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
context "first_initials" do
|
141
|
+
context "when in YAML" do
|
142
|
+
it "returns correct value" do
|
143
|
+
expect(subject.find(:first_initials, "A")).to eql 0
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
context "when not in YAML" do
|
148
|
+
it "returns nil" do
|
149
|
+
expect(subject.find(:first_initials, "AB")).to eql nil
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
context "middle_initials" do
|
155
|
+
context "when in YAML" do
|
156
|
+
it "returns correct value" do
|
157
|
+
expect(subject.find(:middle_initials, "A")).to eql 1
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
context "when not in YAML" do
|
162
|
+
it "returns nil" do
|
163
|
+
expect(subject.find(:middle_initials, "AB")).to eql nil
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
data/spec/parser_spec.rb
CHANGED
@@ -1,8 +1,7 @@
|
|
1
|
-
require '
|
2
|
-
# require 'spec_helper'
|
1
|
+
require 'spec_helper'
|
3
2
|
|
4
3
|
describe Dropmire::Parser do
|
5
|
-
@demo_text =
|
4
|
+
@demo_text = """%FLTALLAHASSEE^JACOBSEN$CONNOR$ALAN^6357 SINKOLA DR^ ?;6360101021210193207=1506199306070=?+! 323124522 E 1602 ECCECC00000?"""
|
6
5
|
parser = Dropmire::Parser.new(@demo_text)
|
7
6
|
subject { parser }
|
8
7
|
|
@@ -10,7 +9,26 @@ describe Dropmire::Parser do
|
|
10
9
|
expect(subject.class).to eql Dropmire::Parser
|
11
10
|
end
|
12
11
|
|
13
|
-
describe "#
|
12
|
+
describe "#address" do
|
13
|
+
it "returns the address section" do
|
14
|
+
expect(subject.address).to eql "%FLTALLAHASSEE"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "#state" do
|
19
|
+
it "returns the correct state" do
|
20
|
+
addr = subject.address
|
21
|
+
|
22
|
+
expect(subject.state(addr)).to eql "FL"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "#city" do
|
27
|
+
it "returns the correct city" do
|
28
|
+
addr = subject.address
|
29
|
+
|
30
|
+
expect(subject.city(addr)).to eql "Tallahassee"
|
31
|
+
end
|
14
32
|
end
|
15
33
|
|
16
34
|
describe "#parse_address" do
|
@@ -18,4 +36,79 @@ describe Dropmire::Parser do
|
|
18
36
|
expect(subject.parse_address).to eql ["Tallahassee", "FL"]
|
19
37
|
end
|
20
38
|
end
|
39
|
+
|
40
|
+
describe "#carrot_string" do
|
41
|
+
it "returns the correct array" do
|
42
|
+
carrot_arr = ["JACOBSEN$CONNOR$ALAN", "6357 SINKOLA DR"]
|
43
|
+
expect(subject.carrot_string).to eql carrot_arr
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe "#names" do
|
48
|
+
it "returns the correct array of strings" do
|
49
|
+
name_hash = {first: "Connor", middle: "Alan", last: "Jacobsen"}
|
50
|
+
expect(subject.names(%w(JACOBSEN CONNOR ALAN))).to eql name_hash
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe "street" do
|
55
|
+
it "returns the correct string" do
|
56
|
+
the_street = "6357 SINKOLA DR"
|
57
|
+
expect(subject.street(the_street)).to eql "6357 Sinkola Dr"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe "#zipcode" do
|
62
|
+
it "returns correct zipcode" do
|
63
|
+
expect(subject.zipcode).to eql "32312"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
describe "#id_string" do
|
68
|
+
it "returns the correct string" do
|
69
|
+
expect(subject.id_string).to eql "6360101021210193207"
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
describe "#iin" do
|
74
|
+
it "returns correct iin" do
|
75
|
+
id_str = subject.id_string
|
76
|
+
expect(subject.iin(id_str)).to eql "636010"
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
describe "#license_num" do
|
81
|
+
context "Florida" do
|
82
|
+
it "returns the correct string" do
|
83
|
+
id_str = subject.id_string
|
84
|
+
expect(subject.license_num(id_str)).to eql "J21210193207"
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
describe "#license_class" do
|
90
|
+
it "returns correct license_class" do
|
91
|
+
expect(subject.license_class).to eql "E"
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
describe "#expiration_date" do
|
96
|
+
it "returns the correct date" do
|
97
|
+
expect(subject.expiration_date).to eql "2015-06"
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
describe "#transform_date" do
|
102
|
+
it "returns Unix format" do
|
103
|
+
expect(subject.transform_date("1707")).to eql "2017-07"
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
describe "#date_of_birth" do
|
108
|
+
context "Florida" do
|
109
|
+
it "returns correct date_of_birth" do
|
110
|
+
expect(subject.date_of_birth).to eql "1993-06-07"
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
21
114
|
end
|
@@ -0,0 +1,188 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Dropmire::Soundex do
|
4
|
+
describe "#soundex" do
|
5
|
+
context "String" do
|
6
|
+
context "Robert" do
|
7
|
+
it "returns R163" do
|
8
|
+
expect(Dropmire::Soundex.soundex("Robert")).to eql 'R163'
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
context "Rupert" do
|
13
|
+
it "returns R163" do
|
14
|
+
expect(Dropmire::Soundex.soundex("Rupert")).to eql 'R163'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
context "Rubin" do
|
19
|
+
it "returns R150" do
|
20
|
+
expect(Dropmire::Soundex.soundex("Rubin")).to eql 'R150'
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
context "Ashcraft" do
|
25
|
+
it "returns A261" do
|
26
|
+
expect(Dropmire::Soundex.soundex("Ashcraft")).to eql 'A261'
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context "Ashcroft" do
|
31
|
+
it "returns A261" do
|
32
|
+
expect(Dropmire::Soundex.soundex("Ashcroft")).to eql 'A261'
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
context "Tymczak" do
|
37
|
+
it "returns T522" do
|
38
|
+
expect(Dropmire::Soundex.soundex("Tymczak")).to eql 'T522'
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context "Pfister" do
|
43
|
+
it "returns P236" do
|
44
|
+
expect(Dropmire::Soundex.soundex("Pfister")).to eql 'P236'
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
context "Array" do
|
50
|
+
it "returns an Array of Soundexs" do
|
51
|
+
name_ary = %w(Robert Rupin Ashcroft Pfister)
|
52
|
+
answers = %w(R163 R150 A261 P236)
|
53
|
+
|
54
|
+
expect(Dropmire::Soundex.soundex(name_ary)).to eql answers
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe "#build_code_for" do
|
60
|
+
context "Robert" do
|
61
|
+
it "returns R163" do
|
62
|
+
expect(Dropmire::Soundex.build_code_for("Robert")).to eql 'R163'
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
context "Rupert" do
|
67
|
+
it "returns R163" do
|
68
|
+
expect(Dropmire::Soundex.build_code_for("Rupert")).to eql 'R163'
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
context "Rubin" do
|
73
|
+
it "returns R150" do
|
74
|
+
expect(Dropmire::Soundex.build_code_for("Rubin")).to eql 'R150'
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
context "Ashcraft" do
|
79
|
+
it "returns A261" do
|
80
|
+
expect(Dropmire::Soundex.build_code_for("Ashcraft")).to eql 'A261'
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
context "Ashcroft" do
|
85
|
+
it "returns A261" do
|
86
|
+
expect(Dropmire::Soundex.build_code_for("Ashcroft")).to eql 'A261'
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
context "Tymczak" do
|
91
|
+
it "returns T522" do
|
92
|
+
expect(Dropmire::Soundex.build_code_for("Tymczak")).to eql 'T522'
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
context "Pfister" do
|
97
|
+
it "returns P236" do
|
98
|
+
expect(Dropmire::Soundex.build_code_for("Pfister")).to eql 'P236'
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
describe "#get code" do
|
104
|
+
context "when code is 1" do
|
105
|
+
it "B" do
|
106
|
+
expect(Dropmire::Soundex.get_code('B')).to eql '1'
|
107
|
+
end
|
108
|
+
|
109
|
+
it "F" do
|
110
|
+
expect(Dropmire::Soundex.get_code('F')).to eql '1'
|
111
|
+
end
|
112
|
+
|
113
|
+
it "P" do
|
114
|
+
expect(Dropmire::Soundex.get_code('P')).to eql '1'
|
115
|
+
end
|
116
|
+
|
117
|
+
it "V" do
|
118
|
+
expect(Dropmire::Soundex.get_code('V')).to eql '1'
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
context "when code is 2" do
|
123
|
+
it "C" do
|
124
|
+
expect(Dropmire::Soundex.get_code('C')).to eql '2'
|
125
|
+
end
|
126
|
+
|
127
|
+
it "G" do
|
128
|
+
expect(Dropmire::Soundex.get_code('G')).to eql '2'
|
129
|
+
end
|
130
|
+
|
131
|
+
it "J" do
|
132
|
+
expect(Dropmire::Soundex.get_code('J')).to eql '2'
|
133
|
+
end
|
134
|
+
|
135
|
+
it "K" do
|
136
|
+
expect(Dropmire::Soundex.get_code('K')).to eql '2'
|
137
|
+
end
|
138
|
+
|
139
|
+
it "Q" do
|
140
|
+
expect(Dropmire::Soundex.get_code('Q')).to eql '2'
|
141
|
+
end
|
142
|
+
|
143
|
+
it "S" do
|
144
|
+
expect(Dropmire::Soundex.get_code('S')).to eql '2'
|
145
|
+
end
|
146
|
+
|
147
|
+
it "X" do
|
148
|
+
expect(Dropmire::Soundex.get_code('X')).to eql '2'
|
149
|
+
end
|
150
|
+
|
151
|
+
it "Z" do
|
152
|
+
expect(Dropmire::Soundex.get_code('Z')).to eql '2'
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
context "when code is 3" do
|
157
|
+
it "D" do
|
158
|
+
expect(Dropmire::Soundex.get_code('D')).to eql '3'
|
159
|
+
end
|
160
|
+
|
161
|
+
it "T" do
|
162
|
+
expect(Dropmire::Soundex.get_code('T')).to eql '3'
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
context "when code is 4" do
|
167
|
+
it "L" do
|
168
|
+
expect(Dropmire::Soundex.get_code('L')).to eql '4'
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
context "when code is 5" do
|
173
|
+
it "M" do
|
174
|
+
expect(Dropmire::Soundex.get_code('M')).to eql '5'
|
175
|
+
end
|
176
|
+
|
177
|
+
it "N" do
|
178
|
+
expect(Dropmire::Soundex.get_code('N')).to eql '5'
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
context "when code is 6" do
|
183
|
+
it "R" do
|
184
|
+
expect(Dropmire::Soundex.get_code('R')).to eql '6'
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dropmire
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Connor Jacobsen
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-10-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -64,14 +64,24 @@ files:
|
|
64
64
|
- LICENSE.txt
|
65
65
|
- README.md
|
66
66
|
- Rakefile
|
67
|
+
- config/first_initial.yml
|
68
|
+
- config/first_name.yml
|
69
|
+
- config/middle_initial.yml
|
67
70
|
- dropmire.gemspec
|
68
71
|
- lib/dropmire.rb
|
72
|
+
- lib/dropmire/ext/string.rb
|
73
|
+
- lib/dropmire/identity.rb
|
74
|
+
- lib/dropmire/name_encoder.rb
|
69
75
|
- lib/dropmire/parser.rb
|
76
|
+
- lib/dropmire/soundex.rb
|
70
77
|
- lib/dropmire/version.rb
|
71
78
|
- spec/demo.txt
|
79
|
+
- spec/identity_spec.rb
|
80
|
+
- spec/name_encoder_spec.rb
|
72
81
|
- spec/parser_spec.rb
|
82
|
+
- spec/soundex_spec.rb
|
73
83
|
- spec/spec_helper.rb
|
74
|
-
homepage:
|
84
|
+
homepage: https://github.com/connorjacobsen/dropmire
|
75
85
|
licenses:
|
76
86
|
- Apache-2.0
|
77
87
|
metadata: {}
|
@@ -97,5 +107,8 @@ specification_version: 4
|
|
97
107
|
summary: A simple way to collect data from US driver's licenses.
|
98
108
|
test_files:
|
99
109
|
- spec/demo.txt
|
110
|
+
- spec/identity_spec.rb
|
111
|
+
- spec/name_encoder_spec.rb
|
100
112
|
- spec/parser_spec.rb
|
113
|
+
- spec/soundex_spec.rb
|
101
114
|
- spec/spec_helper.rb
|