br-utils 0.1.0

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.
Files changed (40) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +120 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +5 -0
  5. data/Gemfile +3 -0
  6. data/LICENSE.txt +21 -0
  7. data/README.md +348 -0
  8. data/Rakefile +6 -0
  9. data/examples/boleto_usage_example.rb +79 -0
  10. data/examples/cep_usage_example.rb +148 -0
  11. data/examples/cnh_usage_example.rb +120 -0
  12. data/examples/cnpj_usage_example.rb +227 -0
  13. data/examples/cpf_usage_example.rb +237 -0
  14. data/examples/currency_usage_example.rb +266 -0
  15. data/examples/date_usage_example.rb +259 -0
  16. data/examples/email_usage_example.rb +321 -0
  17. data/examples/legal_nature_usage_example.rb +437 -0
  18. data/examples/legal_process_usage_example.rb +444 -0
  19. data/examples/license_plate_usage_example.rb +440 -0
  20. data/examples/phone_usage_example.rb +595 -0
  21. data/examples/pis_usage_example.rb +588 -0
  22. data/examples/renavam_usage_example.rb +499 -0
  23. data/examples/voter_id_usage_example.rb +573 -0
  24. data/lib/brazilian-utils/boleto-utils.rb +176 -0
  25. data/lib/brazilian-utils/cep-utils.rb +330 -0
  26. data/lib/brazilian-utils/cnh-utils.rb +88 -0
  27. data/lib/brazilian-utils/cnpj-utils.rb +202 -0
  28. data/lib/brazilian-utils/cpf-utils.rb +192 -0
  29. data/lib/brazilian-utils/currency-utils.rb +226 -0
  30. data/lib/brazilian-utils/data/legal_process_ids.json +38 -0
  31. data/lib/brazilian-utils/date-utils.rb +244 -0
  32. data/lib/brazilian-utils/email-utils.rb +54 -0
  33. data/lib/brazilian-utils/legal-nature-utils.rb +235 -0
  34. data/lib/brazilian-utils/legal-process-utils.rb +240 -0
  35. data/lib/brazilian-utils/license-plate-utils.rb +279 -0
  36. data/lib/brazilian-utils/phone-utils.rb +272 -0
  37. data/lib/brazilian-utils/pis-utils.rb +151 -0
  38. data/lib/brazilian-utils/renavam-utils.rb +113 -0
  39. data/lib/brazilian-utils/voter-id-utils.rb +165 -0
  40. metadata +123 -0
@@ -0,0 +1,499 @@
1
+ require 'brazilian-utils/renavam-utils'
2
+
3
+ include BrazilianUtils::RENAVAMUtils
4
+
5
+ puts "=" * 80
6
+ puts "Brazilian RENAVAM Utils - Usage Examples"
7
+ puts "=" * 80
8
+
9
+ # ============================================================================
10
+ # Section 1: Validating Valid RENAVAM Numbers
11
+ # ============================================================================
12
+ puts "\n1. Validating Valid RENAVAM Numbers"
13
+ puts "-" * 80
14
+
15
+ valid_renavams = [
16
+ '86769597308'
17
+ ]
18
+
19
+ # Calculate a few valid RENAVAMs to demonstrate
20
+ test_bases = ['1234567890', '9876543210', '5555555550', '0123456789', '8676959730']
21
+ test_bases.each do |base|
22
+ dv = send(:calculate_renavam_dv, base + '0')
23
+ valid_renavams << (base + dv.to_s)
24
+ end
25
+
26
+ valid_renavams.each do |renavam|
27
+ valid = is_valid_renavam(renavam)
28
+ status = valid ? '✓ VALID' : '✗ INVALID'
29
+ puts " #{renavam.ljust(15)} → #{status}"
30
+ end
31
+
32
+ # ============================================================================
33
+ # Section 2: Validating Invalid RENAVAM Numbers
34
+ # ============================================================================
35
+ puts "\n2. Validating Invalid RENAVAM Numbers"
36
+ puts "-" * 80
37
+
38
+ invalid_renavams = [
39
+ '12345678901', # Wrong checksum
40
+ '1234567890a', # Contains letter
41
+ '12345678 901', # Contains space
42
+ '12345678', # Too short
43
+ '123456789012', # Too long
44
+ '00000000000', # All zeros
45
+ '11111111111', # All ones
46
+ '99999999999', # All nines
47
+ '', # Empty
48
+ '12345-678901', # Contains hyphen
49
+ '123.456.789.01' # Contains dots
50
+ ]
51
+
52
+ invalid_renavams.each do |renavam|
53
+ valid = is_valid_renavam(renavam)
54
+ status = valid ? '✓ VALID' : '✗ INVALID'
55
+ puts " #{renavam.ljust(20)} → #{status}"
56
+ end
57
+
58
+ # ============================================================================
59
+ # Section 3: Using the is_valid Alias
60
+ # ============================================================================
61
+ puts "\n3. Using the is_valid Alias"
62
+ puts "-" * 80
63
+
64
+ test_renavams = ['86769597308', '12345678901', '11111111111']
65
+
66
+ test_renavams.each do |renavam|
67
+ if is_valid(renavam)
68
+ puts " ✓ #{renavam} is valid"
69
+ else
70
+ puts " ✗ #{renavam} is invalid"
71
+ end
72
+ end
73
+
74
+ # ============================================================================
75
+ # Section 4: Using the valid? Alias
76
+ # ============================================================================
77
+ puts "\n4. Using the valid? Alias"
78
+ puts "-" * 80
79
+
80
+ test_renavams.each do |renavam|
81
+ result = valid?(renavam)
82
+ puts " valid?('#{renavam}') → #{result}"
83
+ end
84
+
85
+ # ============================================================================
86
+ # Section 5: Understanding the Verification Digit Calculation
87
+ # ============================================================================
88
+ puts "\n5. Understanding the Verification Digit Calculation"
89
+ puts "-" * 80
90
+
91
+ puts " Example: RENAVAM 86769597308"
92
+ puts
93
+
94
+ renavam = '86769597308'
95
+ base = renavam[0..9]
96
+ expected_dv = renavam[10].to_i
97
+
98
+ puts " Full RENAVAM: #{renavam}"
99
+ puts " Base (first 10 digits): #{base}"
100
+ puts " Verification digit (11th digit): #{expected_dv}"
101
+ puts
102
+ puts " Calculation steps:"
103
+ puts " 1. Base digits: #{base.chars.join(' ')}"
104
+ puts " 2. Reversed: #{base.reverse.chars.join(' ')}"
105
+ puts " 3. Weights: 2 3 4 5 6 7 8 9 2 3"
106
+ puts
107
+
108
+ # Calculate manually
109
+ reversed = base.reverse.chars.map(&:to_i)
110
+ weights = [2, 3, 4, 5, 6, 7, 8, 9, 2, 3]
111
+ products = reversed.zip(weights).map { |d, w| d * w }
112
+
113
+ puts " 4. Products: #{products.join(' ')}"
114
+ sum = products.sum
115
+ puts " 5. Sum: #{sum}"
116
+ puts " 6. Sum % 11: #{sum % 11}"
117
+ puts " 7. 11 - (sum % 11): #{11 - (sum % 11)}"
118
+ calculated_dv = 11 - (sum % 11)
119
+ final_dv = calculated_dv >= 10 ? 0 : calculated_dv
120
+ puts " 8. Final DV: #{final_dv} #{final_dv >= 10 ? '(>= 10, so use 0)' : ''}"
121
+ puts
122
+ puts " Verification: #{final_dv == expected_dv ? '✓ Matches!' : '✗ Does not match'}"
123
+
124
+ # ============================================================================
125
+ # Section 6: Validating RENAVAM List
126
+ # ============================================================================
127
+ puts "\n6. Validating RENAVAM List"
128
+ puts "-" * 80
129
+
130
+ renavam_list = [
131
+ '86769597308',
132
+ '12345678901',
133
+ '11111111111',
134
+ '1234567890a',
135
+ '12345678',
136
+ '00000000000'
137
+ ]
138
+
139
+ # Add some calculated valid ones
140
+ 5.times do |i|
141
+ base = (i * 987654321).to_s.rjust(10, '0')[0..9]
142
+ dv = send(:calculate_renavam_dv, base + '0')
143
+ renavam_list << (base + dv.to_s)
144
+ end
145
+
146
+ puts " Validating #{renavam_list.length} RENAVAM numbers:"
147
+ puts
148
+
149
+ valid_count = 0
150
+ invalid_count = 0
151
+
152
+ renavam_list.each do |renavam|
153
+ if valid?(renavam)
154
+ valid_count += 1
155
+ puts " ✓ #{renavam}"
156
+ else
157
+ invalid_count += 1
158
+ puts " ✗ #{renavam.ljust(15)} [INVALID]"
159
+ end
160
+ end
161
+
162
+ puts
163
+ puts " Summary:"
164
+ puts " Valid: #{valid_count}"
165
+ puts " Invalid: #{invalid_count}"
166
+ puts " Total: #{renavam_list.length}"
167
+
168
+ # ============================================================================
169
+ # Section 7: Batch Processing
170
+ # ============================================================================
171
+ puts "\n7. Batch Processing"
172
+ puts "-" * 80
173
+
174
+ puts " Processing batch of vehicle registrations:"
175
+ puts
176
+
177
+ vehicles = [
178
+ { plate: 'ABC-1234', renavam: '86769597308' },
179
+ { plate: 'DEF-5678', renavam: '12345678901' },
180
+ { plate: 'GHI-9012', renavam: '11111111111' }
181
+ ]
182
+
183
+ # Add some valid vehicles
184
+ 3.times do |i|
185
+ base = (i * 123456789).to_s.rjust(10, '0')[0..9]
186
+ dv = send(:calculate_renavam_dv, base + '0')
187
+ vehicles << { plate: "XYZ-#{1000 + i}", renavam: base + dv.to_s }
188
+ end
189
+
190
+ valid_vehicles = []
191
+ invalid_vehicles = []
192
+
193
+ vehicles.each do |vehicle|
194
+ if is_valid(vehicle[:renavam])
195
+ valid_vehicles << vehicle
196
+ puts " ✓ #{vehicle[:plate].ljust(10)} - RENAVAM: #{vehicle[:renavam]}"
197
+ else
198
+ invalid_vehicles << vehicle
199
+ puts " ✗ #{vehicle[:plate].ljust(10)} - RENAVAM: #{vehicle[:renavam]} [INVALID]"
200
+ end
201
+ end
202
+
203
+ puts
204
+ puts " Summary:"
205
+ puts " Valid vehicles: #{valid_vehicles.length}"
206
+ puts " Invalid vehicles: #{invalid_vehicles.length}"
207
+
208
+ # ============================================================================
209
+ # Section 8: Edge Cases - All Same Digits
210
+ # ============================================================================
211
+ puts "\n8. Edge Cases - All Same Digits"
212
+ puts "-" * 80
213
+
214
+ puts " RENAVAM cannot be all the same digit:"
215
+
216
+ same_digit_renavams = [
217
+ '00000000000',
218
+ '11111111111',
219
+ '22222222222',
220
+ '99999999999'
221
+ ]
222
+
223
+ same_digit_renavams.each do |renavam|
224
+ valid = is_valid(renavam)
225
+ status = valid ? '✓ VALID' : '✗ INVALID'
226
+ puts " #{renavam} → #{status}"
227
+ end
228
+
229
+ # ============================================================================
230
+ # Section 9: Edge Cases - Leading Zeros
231
+ # ============================================================================
232
+ puts "\n9. Edge Cases - Leading Zeros"
233
+ puts "-" * 80
234
+
235
+ puts " RENAVAM can start with zeros (if checksum is valid):"
236
+
237
+ # Generate some with leading zeros
238
+ leading_zero_bases = ['0000000001', '0000000010', '0000000100', '0000001000']
239
+
240
+ leading_zero_bases.each do |base|
241
+ dv = send(:calculate_renavam_dv, base + '0')
242
+ renavam = base + dv.to_s
243
+ valid = is_valid(renavam)
244
+ status = valid ? '✓ VALID' : '✗ INVALID'
245
+ puts " #{renavam} → #{status}"
246
+ end
247
+
248
+ # ============================================================================
249
+ # Section 10: Edge Cases - Wrong Checksum
250
+ # ============================================================================
251
+ puts "\n10. Edge Cases - Wrong Checksum"
252
+ puts "-" * 80
253
+
254
+ puts " Changing the verification digit makes RENAVAM invalid:"
255
+
256
+ valid_renavam = '86769597308'
257
+ correct_dv = valid_renavam[10]
258
+
259
+ puts " Original: #{valid_renavam} (DV: #{correct_dv})"
260
+ puts " Valid: #{is_valid(valid_renavam)}"
261
+ puts
262
+
263
+ (0..9).each do |dv|
264
+ next if dv.to_s == correct_dv
265
+
266
+ tampered = valid_renavam[0..9] + dv.to_s
267
+ valid = is_valid(tampered)
268
+ status = valid ? '✓ VALID' : '✗ INVALID'
269
+ puts " With DV #{dv}: #{tampered} → #{status}"
270
+ end
271
+
272
+ # ============================================================================
273
+ # Section 11: Calculating Verification Digits
274
+ # ============================================================================
275
+ puts "\n11. Calculating Verification Digits"
276
+ puts "-" * 80
277
+
278
+ puts " Calculating DV for various base numbers:"
279
+ puts
280
+
281
+ test_bases_for_dv = [
282
+ '0000000000',
283
+ '1111111110',
284
+ '1234567890',
285
+ '9876543210',
286
+ '0123456789'
287
+ ]
288
+
289
+ test_bases_for_dv.each do |base|
290
+ dv = send(:calculate_renavam_dv, base + '0')
291
+ renavam = base + dv.to_s
292
+ puts " Base: #{base} → DV: #{dv} → RENAVAM: #{renavam}"
293
+ end
294
+
295
+ # ============================================================================
296
+ # Section 12: Weights Visualization
297
+ # ============================================================================
298
+ puts "\n12. Weights Visualization"
299
+ puts "-" * 80
300
+
301
+ puts " The weights used for DV calculation:"
302
+ puts
303
+ puts " Position (reversed): 1 2 3 4 5 6 7 8 9 10"
304
+ puts " Weight: 2 3 4 5 6 7 8 9 2 3"
305
+ puts
306
+ puts " Example with RENAVAM base '1234567890':"
307
+ puts " Original: 1 2 3 4 5 6 7 8 9 0"
308
+ puts " Reversed: 0 9 8 7 6 5 4 3 2 1"
309
+ puts " Weights: 2 3 4 5 6 7 8 9 2 3"
310
+ puts " Products: 0 27 32 35 36 35 32 27 4 3"
311
+
312
+ base = '1234567890'
313
+ reversed = base.reverse.chars.map(&:to_i)
314
+ weights = [2, 3, 4, 5, 6, 7, 8, 9, 2, 3]
315
+ products = reversed.zip(weights).map { |d, w| d * w }
316
+ sum = products.sum
317
+
318
+ puts " Sum: #{sum}"
319
+ puts " Sum % 11: #{sum % 11}"
320
+ puts " DV: #{11 - (sum % 11)}"
321
+
322
+ # ============================================================================
323
+ # Section 13: Format Validation
324
+ # ============================================================================
325
+ puts "\n13. Format Validation"
326
+ puts "-" * 80
327
+
328
+ puts " Testing various format issues:"
329
+ puts
330
+
331
+ format_tests = [
332
+ { input: '86769597308', desc: 'Valid format' },
333
+ { input: 12345678901, desc: 'Numeric (not string)' },
334
+ { input: '123456789', desc: 'Too short (9 digits)' },
335
+ { input: '12345678901', desc: 'Too long (12 digits)' },
336
+ { input: '1234567890a', desc: 'Contains letter' },
337
+ { input: '12345 67890', desc: 'Contains space' },
338
+ { input: '12345-67890', desc: 'Contains hyphen' },
339
+ { input: '123.456.789.01', desc: 'Contains dots' }
340
+ ]
341
+
342
+ format_tests.each do |test|
343
+ valid = is_valid_renavam(test[:input])
344
+ status = valid ? '✓ VALID' : '✗ INVALID'
345
+ puts " #{status} #{test[:desc].ljust(25)} - Input: #{test[:input].inspect}"
346
+ end
347
+
348
+ # ============================================================================
349
+ # Section 14: Error Handling
350
+ # ============================================================================
351
+ puts "\n14. Error Handling"
352
+ puts "-" * 80
353
+
354
+ edge_cases = [
355
+ nil,
356
+ '',
357
+ [],
358
+ {},
359
+ true,
360
+ false
361
+ ]
362
+
363
+ edge_cases.each do |input|
364
+ puts " Input: #{input.inspect.ljust(20)}"
365
+ puts " is_valid_renavam: #{is_valid_renavam(input)}"
366
+ puts
367
+ end
368
+
369
+ # ============================================================================
370
+ # Section 15: Integration Example - Vehicle Database
371
+ # ============================================================================
372
+ puts "\n15. Integration Example - Vehicle Database"
373
+ puts "-" * 80
374
+
375
+ puts " Simulating vehicle database validation:"
376
+ puts
377
+
378
+ vehicle_database = [
379
+ { id: 1, owner: 'João Silva', renavam: '86769597308' },
380
+ { id: 2, owner: 'Maria Santos', renavam: '12345678901' },
381
+ { id: 3, owner: 'Pedro Costa', renavam: '11111111111' }
382
+ ]
383
+
384
+ # Add some valid entries
385
+ 3.times do |i|
386
+ base = (i * 234567891).to_s.rjust(10, '0')[0..9]
387
+ dv = send(:calculate_renavam_dv, base + '0')
388
+ vehicle_database << {
389
+ id: 4 + i,
390
+ owner: "Owner #{4 + i}",
391
+ renavam: base + dv.to_s
392
+ }
393
+ end
394
+
395
+ puts " Validating #{vehicle_database.length} vehicle records:"
396
+ puts
397
+
398
+ valid_records = []
399
+ invalid_records = []
400
+
401
+ vehicle_database.each do |vehicle|
402
+ if valid?(vehicle[:renavam])
403
+ valid_records << vehicle
404
+ puts " ✓ ID #{vehicle[:id]}: #{vehicle[:owner].ljust(20)} - RENAVAM: #{vehicle[:renavam]}"
405
+ else
406
+ invalid_records << vehicle
407
+ puts " ✗ ID #{vehicle[:id]}: #{vehicle[:owner].ljust(20)} - RENAVAM: #{vehicle[:renavam]} [INVALID]"
408
+ end
409
+ end
410
+
411
+ puts
412
+ puts " Database Statistics:"
413
+ puts " Total records: #{vehicle_database.length}"
414
+ puts " Valid records: #{valid_records.length}"
415
+ puts " Invalid records: #{invalid_records.length}"
416
+ puts " Data quality: #{(valid_records.length * 100.0 / vehicle_database.length).round(1)}%"
417
+
418
+ # ============================================================================
419
+ # Section 16: Comprehensive Validation Test
420
+ # ============================================================================
421
+ puts "\n16. Comprehensive Validation Test"
422
+ puts "-" * 80
423
+
424
+ puts " Generating and validating 20 calculated RENAVAMs:"
425
+ puts
426
+
427
+ all_valid = true
428
+
429
+ 20.times do |i|
430
+ base = (i * 50).to_s.rjust(10, '0')
431
+ dv = send(:calculate_renavam_dv, base + '0')
432
+ renavam = base + dv.to_s
433
+
434
+ valid = is_valid(renavam)
435
+ status = valid ? '✓' : '✗'
436
+ all_valid = false unless valid
437
+
438
+ puts " #{status} #{i + 1}. #{renavam}"
439
+ end
440
+
441
+ puts
442
+ puts " Result: #{all_valid ? '✓ All calculated RENAVAMs are valid!' : '✗ Some RENAVAMs are invalid'}"
443
+
444
+ # ============================================================================
445
+ # Section 17: RENAVAM Structure Visualization
446
+ # ============================================================================
447
+ puts "\n17. RENAVAM Structure Visualization"
448
+ puts "-" * 80
449
+
450
+ sample_renavam = '86769597308'
451
+
452
+ puts " RENAVAM: #{sample_renavam}"
453
+ puts
454
+ puts " Structure:"
455
+ puts " #{sample_renavam}"
456
+ puts " │││││││││││"
457
+ puts " │││││││││││└─ Verification digit (position 11): #{sample_renavam[10]}"
458
+ puts " └┴┴┴┴┴┴┴┴┴┴── Base number (positions 1-10): #{sample_renavam[0..9]}"
459
+ puts
460
+ puts " Total length: 11 digits"
461
+
462
+ # ============================================================================
463
+ # Section 18: Comparison with Similar Systems
464
+ # ============================================================================
465
+ puts "\n18. Comparison with Similar Systems"
466
+ puts "-" * 80
467
+
468
+ puts " RENAVAM characteristics:"
469
+ puts " • Length: 11 digits"
470
+ puts " • Format: No separators (continuous digits)"
471
+ puts " • Checksum: Last digit (weights: 2,3,4,5,6,7,8,9,2,3)"
472
+ puts " • Cannot be: All same digits"
473
+ puts " • Purpose: Vehicle registration identification"
474
+ puts
475
+ puts " Similar to:"
476
+ puts " • CPF: 11 digits with checksum"
477
+ puts " • PIS: 11 digits with checksum"
478
+ puts " • Different from: License plates (letters + numbers)"
479
+
480
+ # ============================================================================
481
+ # Section 20: Best Practices
482
+ # ============================================================================
483
+ puts "\n20. Best Practices"
484
+ puts "-" * 80
485
+
486
+ puts " When working with RENAVAM:"
487
+ puts
488
+ puts " 1. Always validate before storing in database"
489
+ puts " 2. Store as string to preserve leading zeros"
490
+ puts " 3. Do not accept formatted input (no separators)"
491
+ puts " 4. Reject all-same-digit patterns"
492
+ puts " 5. Verify checksum to ensure data integrity"
493
+ puts " 6. Consider adding validation at form input"
494
+ puts " 7. Log validation failures for security monitoring"
495
+ puts " 8. Use consistent method (is_valid, valid?, is_valid_renavam)"
496
+
497
+ puts "\n" + "=" * 80
498
+ puts "RENAVAM Utils Examples Complete!"
499
+ puts "=" * 80