digit_checksum 0.2.2 → 0.2.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 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: