digit_checksum 0.2.2 → 0.2.3

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: a0bce00575ccb77cd11d4b8b8e5304eefac775d7
4
- data.tar.gz: fa112bced8ae776bf2eb88fe1cc00f9f5c2edb5a
3
+ metadata.gz: e098dcc7fc897c32eb09d70d394843796be0da2a
4
+ data.tar.gz: 6205b777875f7348ec6067b717b12151eb22000d
5
5
  SHA512:
6
- metadata.gz: 8f6c902340c35cce05da6fabbd2e8a58993e02896afe4d36f9d432af1a2e833275de9537c6b06ea96d8784d221b2a1160f994026454fe909dcc68100594f0ee8
7
- data.tar.gz: 3617c00620985d2896eb71d9d5c314e5923c1b46c5f071adca984d73ddd119def3b00ddc7f7cc12cfded433b3a2842dc6178f0cbbdddf1c1f7bcbfcc85a4847b
6
+ metadata.gz: d1029ae56d3961add0c57d6b9ccd4883457246bd504bf1a7c625fa1d57fb622d5dfd7f1ec2e2daaf6b3c26ded52889f8899cab89b2be82717aa70be2cce8b1ee
7
+ data.tar.gz: d6d87b10ab1bddc2e0bae2107123d6cc000b5a63f1f0a5c848709bb6ca9469fae3bab49592b26f41819c87a471635169f113a0e47c1a642839928433573bf4f8
data/README.md CHANGED
@@ -17,7 +17,7 @@ One of the greatest abilitys of this library is allowing to check digit checksum
17
17
  Add this line to your application's Gemfile:
18
18
 
19
19
  ```ruby
20
- gem 'digit_checksum', '~> 0.2.2'
20
+ gem 'digit_checksum', '~> 0.2.3'
21
21
  ```
22
22
 
23
23
  And then execute:
@@ -41,20 +41,18 @@ Don't you believe me? See for yourself an example:
41
41
  require 'digit_checksum'
42
42
 
43
43
  class CNPJ < DigitChecksum::BaseDocument
44
- # weights masks that will be used to calculate each check digit
45
44
  set_verify_digits_weights first: %w(5 4 3 2 9 8 7 6 5 4 3 2),
46
- second: %w(6 5 4 3 2 9 8 7 6 5 4 3 2)
45
+ second: %w(6 5 4 3 2 9 8 7 6 5 4 3 2)
46
+
47
+ # MOD 11
48
+ set_division_modulo 11
47
49
 
48
50
  # remove any non digit from document number
49
51
  set_clear_number_regexp %r{[^(\d+)]}
50
52
 
51
- # use modulo 11 as algorithm (can be any value)
52
- set_division_factor_modulo 11
53
-
54
53
  # match format such as: 99.999.999/9999-99 | 99-999-999/9999-99 | 99999999/999999 | 99999999999999
55
- set_valid_format_regexp %r{(\d{2})[-.]?(\d{3})[-.]?(\d{3})[\/]?(\d{4})[-.]?(\d{2})}
54
+ set_format_regexp %r{(\d{2})[-.]?(\d{3})[-.]?(\d{3})[\/]?(\d{4})[-.]?(\d{2})}
56
55
 
57
- # mask utilized to prettify doc number
58
56
  set_pretty_format_mask %(%s.%s.%s/%s-%s)
59
57
 
60
58
  # numbers sampled to generate new document numbers
@@ -72,7 +70,7 @@ CNPJ.generate # "79.552.921/0786-55"
72
70
  # without pretty formating
73
71
  CNPJ.generate(false) # 85215313606778
74
72
 
75
- # You can calculate only random root numbers
73
+ # You can generate only random root numbers
76
74
  root_numbers = CNPJ.generate_root_numbers
77
75
  # => [3, 8, 9, 3, 2, 5, 9, 5, 0, 2, 6, 6]
78
76
 
@@ -81,7 +79,8 @@ CNPJ.calculate_verify_digits(root_numbers) # [6,7]
81
79
  # To insert the verify digits in the CORRECT positions
82
80
  # Remember: The correct position MAY NOT be the last positions
83
81
  # So use `append_verify_digits` to handle this
84
- CNPJ.pretty(CNPJ.append_verify_digits(root_numbers))
82
+
83
+ CNPJ.pretty(CNPJ.append_verify_digits!(root_numbers))
85
84
  => "38.932.595/0266-67"
86
85
  ```
87
86
 
@@ -94,19 +93,13 @@ CNPJ.calculate_verify_digits("123.456.78/0001") # [9,5]
94
93
  # invalid format
95
94
  CNPJ.calculate_verify_digits("123.456.78/00001") # []
96
95
 
97
- CNPJ.pretty(CNPJ.append_verify_digits("123.456.78/0001")) # "123.456.78/0001-95"
96
+ CNPJ.pretty(CNPJ.append_verify_digits!("12.345.678/0001")) # "12.345.678/0001-95
98
97
 
99
98
  document = "123.456.78/0001-95"
100
- CNPJ.remove_verify_digits!(document)
101
- # [9,5]
102
- document
103
- # => 123456780001
104
- CNPJ.pretty(CNPJ.append_verify_digits(document))
105
- # => "12.345.678/0001-95"
99
+ CNPJ.remove_verify_digits!(document) => # [9,5]
100
+ document # => 123456780001
106
101
 
107
- # The last two characters position
108
- CNPJ.obtain_verify_digits_positions
109
- # => [12, 13]
102
+ CNPJ.pretty(CNPJ.append_verify_digits!(document)) # => "12.345.678/0001-95"
110
103
 
111
104
  ```
112
105
 
@@ -115,12 +108,12 @@ CNPJ.obtain_verify_digits_positions
115
108
  # convenience methods to check if document is valid
116
109
 
117
110
  # invalid format
118
- CNPJ.valid?("123.456.78/0001") # false
119
- CNPJ.invalid?("123.456.78/0001") # true
111
+ CNPJ.valid?("123.456.78/0001") # => false
112
+ CNPJ.invalid?("123.456.78/0001") # => true
120
113
 
121
114
  # valid format
122
- CNPJ.valid?("123.456.78/0001-95") # true
123
- CNPJ.valid?(12345678000195) # true
115
+ CNPJ.valid?("123.456.78/0001-95") # => true
116
+ CNPJ.valid?(12345678000195) # => true
124
117
 
125
118
  ```
126
119
 
@@ -129,20 +122,18 @@ CNPJ.valid?(12345678000195) # true
129
122
  ```ruby
130
123
 
131
124
  # Get a array representation of document number
132
- CNPJ.normalize_number("123.456.78/0001-95")
125
+ CNPJ.normalize("123.456.78/0001-95")
133
126
  # => [1, 2, 3, 4, 5, 6, 7, 8, 0, 0, 0, 1, 9, 5]
134
127
 
135
128
  # also aliased as CNPJ.pretty_formatted(number) or CNPJ.formatted(number)
136
129
  CNPJ.pretty("12345678000195") # "123.456.78/0001-95"
137
130
 
138
131
  # also aliased as CNPJ.clear_number(number)
139
- CNPJ.stripped("123.456.78/0001-95")
140
- # => "12345678000195"
132
+ CNPJ.strip("123.456.78/0001-95") # => "12345678000195"
141
133
  ```
142
134
 
143
135
  See `examples/`for more detailed samples.
144
136
 
145
-
146
137
  ---
147
138
 
148
139
  ### Custom verify digits positions
@@ -152,48 +143,106 @@ to calculate check digits in any position in the middle of the document number,
152
143
 
153
144
  ```ruby
154
145
  class MyDocument < DigitChecksum::BaseDocument
155
- set_division_factor_modulo 11
146
+
147
+ set_division_modulo 11
156
148
 
157
149
  set_clear_number_regexp %r{[^(\d+)]}
158
150
 
159
- set_root_documents_digits_count 10
151
+ set_root_digits_count 10
160
152
 
161
153
  set_verify_digits_positions [8, 11]
162
154
 
163
155
  set_verify_digits_weights first: %w(1 3 4 5 6 7 8 10),
164
156
  last: %w(3 2 10 9 8 7 6 5 4 3 2)
165
157
 
166
- set_valid_format_regexp %r{(\d{3})[-.]?(\d{3})[-.]?(\d{3})[-.]?(\d{3})}
158
+ set_format_regexp %r{(\d{3})[-.]?(\d{3})[-.]?(\d{3})[-.]?(\d{3})}
167
159
 
168
160
  set_pretty_format_mask %(%s.%s.%s.%s)
169
161
 
170
162
  set_generator_numbers (0..9).to_a
171
163
  end
172
164
 
173
- MyDocument.obtain_verify_digits_positions # [8, 11]
165
+
166
+ MyDocument.get_verify_digits_positions # [8, 11]
167
+
174
168
  # document number without check digits
175
- MyDocument.calculate_verify_digits("110.042.49.11")
176
- # => [1, 3]
177
- document = MyDocument.append_verify_digits("110.042.49.11")
169
+ MyDocument.calculate_verify_digits("110.042.49.11") # => [1, 3]
170
+
171
+ document = MyDocument.append_verify_digits!("110.042.49.11")
178
172
  # => "110042491113"
179
- MyDocument.pretty(document)
180
- # => "110.042.491.113"
181
- MyDocument.remove_verify_digits!(document)
182
- # => [1, 3]
183
- document
184
- # => "1100424911"
185
- document = MyDocument.append_verify_digits(document)
173
+
174
+ MyDocument.pretty(document) # => "110.042.491.113"
175
+
176
+ MyDocument.remove_verify_digits!(document) # => [1, 3]
177
+
178
+ document # => "1100424911"
179
+ document = MyDocument.append_verify_digits!(document)
180
+
186
181
  # => "110042491113"
187
- MyDocument.pretty(document)
188
- # => "110.042.491.113"
182
+ MyDocument.pretty(document) # => "110.042.491.113"
183
+
189
184
  # document number with check digits in the right positions(8, 11)
190
- MyDocument.valid?("110.042.491.113")
191
- # => true
185
+ MyDocument.valid?("110.042.491.113") # => true
186
+
192
187
  # document number with wrong check digits in the right positions
193
- MyDocument.valid?("110.042.492.113")
194
- # => false
195
- MyDocument.pretty(MyDocument.append_verify_digits("110.042.49.11"))
188
+ MyDocument.valid?("110.042.492.113") # => false
189
+
190
+ MyDocument.pretty(MyDocument.append_verify_digits!("110.042.49.11"))
196
191
  # => "110.042.491.113"
192
+
193
+ doc = MyDocument.generate # => "286.670.374.780"
194
+
195
+ MyDocument.valid?(doc) # =: true
196
+ ```
197
+
198
+ ---
199
+
200
+ ## PORO - Plain Old Ruby Objects API
201
+
202
+ All API demonstrated in this documentation (mostly class methods call) are **simple instance methods delegations to a Ruby object instance**, you can work directly with objects in this way:
203
+
204
+ ```ruby
205
+ object = CNPJ.new("53.091.177/2847-09")
206
+
207
+ object.valid? # true
208
+
209
+ # Try to get verify digits without calculating
210
+ # Just search in the right positions in number
211
+ object.current_verify_digits # [0, 9]
212
+
213
+ # Permanently remove verify digits from number
214
+ object.remove_verify_digits! # [0, 9]
215
+
216
+ # Try to get verify digits without calculating
217
+ object.current_verify_digits # []
218
+
219
+ object.number # object.to_s => "530911772847"
220
+
221
+ object.valid? # false
222
+
223
+ # Just calculate the verify digits, dont append to number
224
+ object.calculate_verify_digits # [0, 9]
225
+
226
+ # Use the `calculate_verify_digits` methods and append the digits in the RIGHT positions
227
+ object.append_verify_digits! # "53091177284709"
228
+
229
+ object.pretty # => "53.091.177/2847-09"
230
+
231
+ object.normalize
232
+ # => [5, 3, 0, 9, 1, 1, 7, 7, 2, 8, 4, 7, 0, 9]
233
+
234
+ object.strip # "53091177284709"
235
+
236
+ object.size # 14
237
+
238
+ object.root_digits_count # 12
239
+
240
+ object.verify_digits_count # 2
241
+
242
+ # root_digits_count + verify_digits_count
243
+ object.full_size # 14
244
+
245
+ object.verify_digits_positions # [12, 13]
197
246
  ```
198
247
 
199
248
  ---
@@ -3,13 +3,13 @@ class CNPJ < DigitChecksum::BaseDocument
3
3
  second: %w(6 5 4 3 2 9 8 7 6 5 4 3 2)
4
4
 
5
5
  # MOD 11
6
- set_division_factor_modulo 11
6
+ set_division_modulo 11
7
7
 
8
8
  # remove any non digit from document number
9
9
  set_clear_number_regexp %r{[^(\d+)]}
10
10
 
11
11
  # match format such as: 99.999.999/9999-99 | 99-999-999/9999-99 | 99999999/999999 | 99999999999999
12
- set_valid_format_regexp %r{(\d{2})[-.]?(\d{3})[-.]?(\d{3})[\/]?(\d{4})[-.]?(\d{2})}
12
+ set_format_regexp %r{(\d{2})[-.]?(\d{3})[-.]?(\d{3})[\/]?(\d{4})[-.]?(\d{2})}
13
13
 
14
14
  set_pretty_format_mask %(%s.%s.%s/%s-%s)
15
15
 
@@ -25,5 +25,5 @@ CNPJ.valid?(69739073000104) # true
25
25
  CNPJ.valid?("38.485.271/0001-57") # true
26
26
 
27
27
  CNPJ.calculate_verify_digits("423.819.53/0001") # [9,7]
28
- CNPJ.pretty_formatted("69739073000104") # "69.739.073/0001-04"
29
- CNPJ.clear_document_number("38.485.271/0001-57") # 38485271000157
28
+ CNPJ.pretty("69739073000104") # "69.739.073/0001-04"
29
+ CNPJ.strip("38.485.271/0001-57") # 38485271000157
@@ -3,13 +3,13 @@ class CPF < DigitChecksum::BaseDocument
3
3
  second: %w(11 10 9 8 7 6 5 4 3 2)
4
4
 
5
5
  # MOD 11
6
- set_division_factor_modulo 11
6
+ set_division_modulo 11
7
7
 
8
8
  # remove any non digit from document number
9
9
  set_clear_number_regexp %r{[^(\d+)]}
10
10
 
11
11
  # match format such as: 999.999.999-99 | 999-999-999-99 | 99999999999
12
- set_valid_format_regexp %r{(\d{3})[-.]?(\d{3})[-.]?(\d{3})[-.]?(\d{2})}
12
+ set_format_regexp %r{(\d{3})[-.]?(\d{3})[-.]?(\d{3})[-.]?(\d{2})}
13
13
 
14
14
  set_pretty_format_mask %(%s.%s.%s-%s)
15
15
 
@@ -25,5 +25,5 @@ CPF.valid?(31777259185) # true
25
25
  CPF.valid?("315.844.227-26") # true
26
26
 
27
27
  CPF.calculate_verify_digits("315.844.227") # [2, 6]
28
- CPF.pretty_formatted("31777259185") # "315.844.227-26"
29
- CPF.clear_document_number("315.844.227-26")
28
+ CPF.pretty("31777259185") # "315.844.227-26"
29
+ CPF.strip("315.844.227-26") # 31584422726
@@ -12,7 +12,7 @@ class H4ck < DigitChecksum::BaseDocument
12
12
 
13
13
  PROGRAMMINGS_LANGUAGES.default = 'Unknown'
14
14
 
15
- set_division_factor_modulo 11
15
+ set_division_modulo 11
16
16
 
17
17
  set_verify_digits_weights first: %w(17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2),
18
18
  second: %w(18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2),
@@ -23,7 +23,7 @@ class H4ck < DigitChecksum::BaseDocument
23
23
 
24
24
  # 0101&&1111(0x01)||[16]<07>!29
25
25
  # Ex: 0101&&1111(0x01)||[16]<07>!29-110
26
- set_valid_format_regexp %r{(\d{4})(\d{4})\(?[0x]?(\d{2})\)?\|?\|?\[?(\d{2})\]?\<?(\d{2})\>?\!?(\d{2})\-?(\d{3})}
26
+ set_format_regexp %r{(\d{4})(\d{4})\(?[0x]?(\d{2})\)?\|?\|?\[?(\d{2})\]?\<?(\d{2})\>?\!?(\d{2})\-?(\d{3})}
27
27
 
28
28
  # XXXX&&XXXX(0xZZ)||[YY]<MM>!DD-VVV;
29
29
  set_pretty_format_mask %(%s&&%s(0x%s)||[%s]<%s>!%s-%s;)
@@ -31,9 +31,8 @@ class H4ck < DigitChecksum::BaseDocument
31
31
  # numbers sampled to generate new document numbers
32
32
  set_generator_numbers (0..9).to_a
33
33
 
34
- def self.favorite_language(document_number)
35
- document_number = normalize_document_number(document_number)
36
- languange_identifier = document_number[8..9].join
34
+ def favorite_language
35
+ languange_identifier = normalize[8..9].join
37
36
 
38
37
  PROGRAMMINGS_LANGUAGES[languange_identifier]
39
38
  end
@@ -45,11 +44,11 @@ invalid_doc_number = "0101&&1111(0x01)||[16]<07>!29-841"
45
44
 
46
45
  H4ck.generate
47
46
  H4ck.valid?(H4ck.generate)
48
- H4ck.normalize_document_number_to_s(root_doc_number) # "0101111101160729"
47
+ H4ck.strip(root_doc_number) # "0101111101160729"
49
48
  H4ck.calculate_verify_digits(root_doc_number) # [8,4,0]
50
49
  H4ck.valid?(root_doc_number) # false
51
50
  H4ck.valid?(valid_doc_number) # true
52
51
  H4ck.valid?(invalid_doc_number) # false
53
52
 
54
- H4ck.favorite_language(valid_doc_number) # C#
55
- H4ck.favorite_language("0101&&1111(0x04)||[16]<07>!29-840") # Python
53
+ H4ck.new(valid_doc_number).favorite_language # C#
54
+ H4ck.new("0101&&1111(0x04)||[16]<07>!29-840").favorite_language # Python
@@ -1,5 +1,12 @@
1
1
  require "digit_checksum/version"
2
2
  require "digit_checksum/base_document"
3
+ require "digit_checksum/helpers"
4
+ require "digit_checksum/delegators"
3
5
 
4
6
  module DigitChecksum
7
+ class BaseDocument
8
+
9
+ extend Helpers
10
+
11
+ end
5
12
  end
@@ -1,219 +1,217 @@
1
1
  module DigitChecksum
2
2
  class BaseDocument
3
3
 
4
- CONSTANTS_MAP = [
5
- :root_documents_digits_count,
4
+ CLASS_METHODS = [
6
5
  :verify_digits_positions,
7
6
  :digits_ignore_positions,
8
- :division_factor_modulo,
9
7
  :verify_digits_weights,
10
8
  :clear_number_regexp,
11
- :valid_format_regexp,
9
+ :root_digits_count,
12
10
  :pretty_format_mask,
13
11
  :generator_numbers,
14
- :document_length
12
+ :division_modulo,
13
+ :document_length,
14
+ :format_regexp
15
15
  ]
16
16
 
17
- class << self
18
- def generate(formatted = true)
19
- document_number = append_verify_digits(generate_root_numbers)
20
-
21
- formatted ? pretty_formatted(document_number) : document_number
17
+ CLASS_METHODS.each do |const_name|
18
+ define_singleton_method "get_#{const_name}" do
19
+ self.const_get(const_name.to_s.upcase)
22
20
  end
23
21
 
24
- def append_verify_digits(document_number)
25
- document_number = normalize_number(document_number)
26
- verify_digits = calculate_verify_digits(document_number)
27
-
28
- obtain_verify_digits_positions.each_with_index {|position, index|
29
- document_number.insert(position + index, verify_digits.shift)
30
- }
31
-
32
- normalize_number_to_s(document_number.compact)
22
+ define_singleton_method "set_#{const_name}" do |value|
23
+ self.const_set(const_name.to_s.upcase, value).freeze
33
24
  end
34
25
 
35
- def generate_root_numbers
36
- root_document_digits_count.times.map { get_generator_numbers.sample }
26
+ define_method "get_#{const_name}" do
27
+ self.class.const_get(const_name.to_s.upcase)
37
28
  end
29
+ end
38
30
 
39
- def valid?(document_number)
40
- # remove all non digits and return an string to be matched with mask
41
- normalized_document = normalize_number_to_s(document_number)
31
+ attr_accessor :number
42
32
 
43
- # if document is empty
44
- return false if normalized_document.nil? || normalized_document.empty?
33
+ def initialize(number)
34
+ @number = stripped(number)
35
+ end
45
36
 
46
- # if document dont match the exact size, it's invalid
47
- return false unless valid_length?(normalized_document)
37
+ def valid?
38
+ # if document is empty or dont match the exact size, it's invalid
39
+ return false if (empty? || !valid_length?)
48
40
 
49
- # remove verify digits to be verified
50
- verify_digits = remove_verify_digits!(normalized_document)
41
+ # match current verify digits with calculate through modulo operation
42
+ current_verify_digits == calculate_verify_digits
43
+ end
51
44
 
52
- # calculate the new digits based on root document number
53
- digits = calculate_verify_digits(normalized_document)
45
+ def invalid?
46
+ !valid?
47
+ end
54
48
 
55
- verify_digits == digits
56
- end
49
+ def empty?
50
+ @number.nil? || @number.empty?
51
+ end
57
52
 
58
- def remove_verify_digits!(document_number)
59
- document_number.gsub!(get_clear_number_regexp, '')
53
+ def valid_length?
54
+ size == full_size
55
+ end
60
56
 
61
- obtain_verify_digits_positions.each_with_index.flat_map {|position, index|
62
- document_number.slice!((position - index), 1)
63
- }.map(&:to_i)
64
- end
57
+ def full_size
58
+ (root_digits_count + verify_digits_count)
59
+ end
65
60
 
66
- def obtain_verify_digits_positions
67
- begin
68
- get_verify_digits_positions
69
- # when value its not set
70
- rescue NameError => e
71
- default_verify_digits_position
72
- end
73
- end
61
+ def size
62
+ normalize.length
63
+ end
74
64
 
75
- def default_verify_digits_position
76
- verify_digits_count.times.map {|i| root_document_digits_count + i }
77
- end
65
+ alias :length :size
78
66
 
79
- def invalid?(document_number)
80
- !valid?(document_number)
81
- end
67
+ def current_verify_digits
68
+ remove_verify_digits(@number.dup)
69
+ end
82
70
 
83
- def calculate_verify_digits(document_number)
84
- return [] unless correct_length_based_on_first_mask?(document_number)
71
+ def calculate_verify_digits
72
+ number = without_verify_digits(@number)
73
+ digits = []
74
+ digits_positions = verify_digits_positions.dup
85
75
 
86
- document_number = normalize_number(document_number)
87
- division_modulo = get_division_factor_modulo
88
- digits_positions = obtain_verify_digits_positions.dup
89
- digits = []
76
+ return [] unless number.size == root_digits_count
90
77
 
91
- get_verify_digits_weights.each_with_index do |data, index|
92
- position, mask = *data
93
- current_document = root_document_number(document_number, mask)
94
- verify_digit = calculate_verify_digit(current_document, mask, division_modulo)
78
+ get_verify_digits_weights.each_with_index do |data, index|
79
+ position, weights = *data
95
80
 
96
- digits << verify_digit
97
- digit_position = digits_positions.shift + index
81
+ current_number = normalized(number, weights.size)
82
+ verify_digit = calculate_verify_digit(current_number, weights)
98
83
 
99
- # just update ref
100
- document_number.insert(digit_position, verify_digit)
101
- end
84
+ # just update ref to calculate next digit
85
+ number.insert((digits_positions.shift + index), verify_digit)
102
86
 
103
- digits
87
+ digits << verify_digit
104
88
  end
105
89
 
106
- def root_document_number(document_number, mask = nil)
107
- mask ||= get_verify_digits_weights.values[0]
90
+ digits
91
+ end
108
92
 
109
- normalize_document_number(document_number, mask.size)
110
- end
93
+ def remove_verify_digits!
94
+ remove_verify_digits(@number)
95
+ end
111
96
 
112
- def root_document_number_to_s(document_number, mask = nil)
113
- root_document_number(document_number, mask).join
114
- end
97
+ def append_verify_digits!
98
+ digits = calculate_verify_digits
115
99
 
116
- def normalize_document_number(document_number, length = nil)
117
- document_number = clear_document_number(document_number).split(//).map(&:to_i)
100
+ if (!valid_length? && digits != current_verify_digits)
101
+ @number = normalize
118
102
 
119
- length.nil? ? document_number : document_number[0, length]
103
+ verify_digits_positions.each_with_index.flat_map {|position, index|
104
+ # position + index
105
+ @number.insert(position, digits.shift)
106
+ }
120
107
  end
121
108
 
122
- def normalize_document_number_to_s(document_number, length = nil)
123
- normalize_document_number(document_number, length).join
124
- end
109
+ @number = stripped(@number)
110
+ end
125
111
 
126
- def clear_document_number(document_number)
127
- document_number.to_s.gsub(get_clear_number_regexp, '')
128
- end
112
+ def normalize
113
+ normalized(@number)
114
+ end
115
+
116
+ def pretty
117
+ numbers = @number.to_s.scan(get_format_regexp).flatten
118
+ numbers.empty? ? '' : (get_pretty_format_mask % numbers)
119
+ end
129
120
 
130
- def pretty_formatted(document_number)
131
- normalized_doc = normalize_number_to_s(document_number)
121
+ def strip
122
+ stripped(@number)
123
+ end
132
124
 
133
- return "" if normalized_doc.empty?
125
+ def to_s
126
+ @number
127
+ end
134
128
 
135
- numbers = normalized_doc.to_s.scan(get_valid_format_regexp).flatten
129
+ def verify_digits_count
130
+ get_verify_digits_weights.size
131
+ end
136
132
 
137
- # document has a value but it's not valid
138
- return "" if numbers.empty?
133
+ def root_digits_count
134
+ self.class.root_digits_count
135
+ end
139
136
 
140
- get_pretty_format_mask % numbers
137
+ def verify_digits_positions
138
+ begin
139
+ get_verify_digits_positions
140
+ # when value its not set
141
+ rescue NameError => e
142
+ default_verify_digits_position
141
143
  end
144
+ end
142
145
 
143
- def calculate_verify_digit(document_number, mask, division_factor)
144
- digits = calculate_digits_data(document_number, mask, division_factor)
146
+ alias :as_array :normalize
147
+ alias :clear :strip
148
+ alias :formatted :pretty
145
149
 
146
- digits[:verify_digit].to_i
147
- end
150
+ private
151
+ def stripped(number)
152
+ number.to_s.gsub(get_clear_number_regexp, '')
153
+ end
148
154
 
149
- def calculate_digits_data(document_number, mask, division_factor)
150
- sum = calculate_digits_sum(document_number, mask)
151
- quotient = (sum / division_factor)
155
+ def normalized(number, length = nil)
156
+ number = stripped(number).split(//).map(&:to_i)
152
157
 
153
- rest = calculate_digits_sum_rest(sum, quotient, division_factor)
158
+ length.nil? ? number : number[0, length]
159
+ end
154
160
 
155
- { sum: sum, quotient: quotient, rest: rest, verify_digit: digit_verify(rest, division_factor) }
156
- end
161
+ def remove_verify_digits(number)
162
+ return [] unless number.size == full_size
157
163
 
158
- def calculate_digits_sum_rest(sum, quotient, division_factor)
159
- (sum % division_factor)
160
- end
164
+ verify_digits_positions.each_with_index.flat_map {|position, index|
165
+ number.slice!(position - index, 1)
166
+ }.map(&:to_i)
167
+ end
161
168
 
162
- def calculate_digits_sum(document_number, mask)
163
- normalized_document_number = normalize_document_number(document_number)
169
+ def without_verify_digits(number)
170
+ number = normalized(number)
164
171
 
165
- normalized_document_number.each_with_index.map {|n,i| n.to_i * mask[i].to_i }.reduce(:+).to_f
166
- end
172
+ return number unless number.size == full_size
167
173
 
168
- def digit_verify(quotient_rest, division_factor)
169
- rest = (division_factor - quotient_rest).to_i
174
+ remove_verify_digits(number) and number
175
+ end
170
176
 
171
- # if rest has two digits(checkdigit must be a single digit), force 0
172
- return 0 if rest >= 10
177
+ def default_verify_digits_position
178
+ verify_digits_count.times.map {|i| root_digits_count + i }
179
+ end
173
180
 
174
- rest
175
- end
181
+ def calculate_verify_digit(number, weights)
182
+ data = calculate_digits_data(number, weights)
176
183
 
177
- def first_verify_mask
178
- get_verify_digits_weights.values[0]
179
- end
184
+ calc_verify_digit(data[:rest])
185
+ end
180
186
 
181
- def verify_digits_count
182
- get_verify_digits_weights.size
183
- end
187
+ def calculate_digits_data(number, weights)
188
+ sum = reduce_digits_weights(number, weights)
189
+ quotient = (sum / get_division_modulo)
190
+ rest = calculate_rest(sum, quotient)
184
191
 
185
- def root_document_digits_count
186
- begin
187
- get_root_documents_digits_count
188
- rescue NameError => e
189
- first_verify_mask.size
190
- end
191
- end
192
+ { sum: sum, quotient: quotient, rest: rest }
193
+ end
192
194
 
193
- def correct_length_based_on_first_mask?(document_number)
194
- normalize_document_number(document_number).size == root_document_digits_count
195
- end
195
+ def reduce_digits_weights(number, weights)
196
+ number = normalized(number)
196
197
 
197
- def valid_length?(document_number)
198
- normalize_document_number(document_number).size == root_document_digits_count + verify_digits_count
199
- end
198
+ number.each_with_index.map {|n,i|
199
+ n.to_i * weights[i].to_i
200
+ }.reduce(:+).to_f
201
+ end
200
202
 
201
- alias :normalize_number_to_s :normalize_document_number_to_s
202
- alias :normalize_number :normalize_document_number
203
- alias :clear_number :clear_document_number
204
- alias :stripped :clear_document_number
205
- alias :formatted :pretty_formatted
206
- alias :pretty :pretty_formatted
207
-
208
- CONSTANTS_MAP.each do |const_name|
209
- define_method "get_#{const_name}" do
210
- self.const_get(const_name.to_s.upcase)
211
- end
212
-
213
- define_method "set_#{const_name}" do |value|
214
- self.const_set(const_name.to_s.upcase, value)
215
- end
216
- end
203
+ def calculate_rest(sum, quotient)
204
+ (sum % get_division_modulo)
217
205
  end
206
+
207
+ def calc_verify_digit(quotient_rest)
208
+ rest = (get_division_modulo - quotient_rest).to_i
209
+
210
+ # if rest has two digits(checkdigit must be a single digit), force 0
211
+ return 0 if rest >= 10
212
+
213
+ rest
214
+ end
215
+
218
216
  end
219
217
  end
@@ -0,0 +1,25 @@
1
+ module DigitChecksum
2
+ class BaseDocument
3
+
4
+ CLASS_METHODS_DELEGATES = [
5
+ :valid?,
6
+ :invalid?,
7
+ :pretty,
8
+ :strip,
9
+ :normalize,
10
+ :as_array,
11
+ :formatted,
12
+ :clear,
13
+ :remove_verify_digits!,
14
+ :append_verify_digits!,
15
+ :calculate_verify_digits,
16
+ :valid_length?
17
+ ]
18
+
19
+ CLASS_METHODS_DELEGATES.each do |method_name|
20
+ define_singleton_method method_name do |number|
21
+ new(number).public_send(method_name)
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,33 @@
1
+ module DigitChecksum
2
+ module Helpers
3
+ def generate(pretty = true)
4
+ number = new(generate_root_numbers)
5
+ number.append_verify_digits!
6
+
7
+ pretty ? number.pretty : number.to_s
8
+ end
9
+
10
+ def generate_root_numbers
11
+ root_digits_count.times.map { get_generator_numbers.sample }
12
+ end
13
+
14
+ def root_digits_count
15
+ begin
16
+ get_root_digits_count
17
+ rescue NameError => e
18
+ first_verify_mask = get_verify_digits_weights.values[0]
19
+ first_verify_mask.size
20
+ end
21
+ end
22
+
23
+ def root_number(number, mask = nil)
24
+ mask ||= get_verify_digits_weights.values[0]
25
+
26
+ new(number).normalize.slice(0, mask.size)
27
+ end
28
+
29
+ def root_number_to_s(number, mask = nil)
30
+ root_number(number, mask).join
31
+ end
32
+ end
33
+ end
@@ -1,3 +1,3 @@
1
1
  module DigitChecksum
2
- VERSION = "0.2.2"
2
+ VERSION = "0.2.3"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: digit_checksum
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rafael Fidelis
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-08-08 00:00:00.000000000 Z
11
+ date: 2016-08-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -90,6 +90,8 @@ files:
90
90
  - examples/h4ck.rb
91
91
  - lib/digit_checksum.rb
92
92
  - lib/digit_checksum/base_document.rb
93
+ - lib/digit_checksum/delegators.rb
94
+ - lib/digit_checksum/helpers.rb
93
95
  - lib/digit_checksum/version.rb
94
96
  homepage: https://github.com/fidelisrafael/digit_checksum
95
97
  licenses: