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,573 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Voter ID Utils - Comprehensive Usage Examples
4
+ # ===============================================
5
+ # This file demonstrates all features of the VoterIdUtils module
6
+ # for working with Brazilian voter IDs (Título de Eleitor)
7
+
8
+ require_relative '../lib/brazilian-utils/voter-id-utils'
9
+
10
+ # For convenience, include the module
11
+ include BrazilianUtils::VoterIdUtils
12
+
13
+ puts "=" * 80
14
+ puts "BRAZILIAN VOTER ID UTILS - USAGE EXAMPLES"
15
+ puts "=" * 80
16
+
17
+ # ============================================================================
18
+ # SECTION 1: Basic Validation
19
+ # ============================================================================
20
+ puts "\n1. BASIC VALIDATION"
21
+ puts "-" * 80
22
+
23
+ voter_ids = [
24
+ '690847092828', # Valid SP voter ID
25
+ '163204010922', # Valid MG voter ID
26
+ '000000000191', # Valid RJ voter ID
27
+ '123456780140' # Valid RS voter ID
28
+ ]
29
+
30
+ puts "\nValidating voter IDs:"
31
+ voter_ids.each do |voter_id|
32
+ result = is_valid_voter_id(voter_id)
33
+ puts " #{voter_id}: #{result ? '✓ VALID' : '✗ INVALID'}"
34
+ end
35
+
36
+ # Output:
37
+ # 690847092828: ✓ VALID
38
+ # 163204010922: ✓ VALID
39
+ # 000000000191: ✓ VALID
40
+ # 123456780140: ✓ VALID
41
+
42
+ # ============================================================================
43
+ # SECTION 2: Validation with Alias Methods
44
+ # ============================================================================
45
+ puts "\n2. VALIDATION WITH ALIAS METHODS"
46
+ puts "-" * 80
47
+
48
+ voter_id = '690847092828'
49
+
50
+ puts "\nDifferent ways to validate the same voter ID:"
51
+ puts " is_valid_voter_id('#{voter_id}'): #{is_valid_voter_id(voter_id)}"
52
+ puts " valid_voter_id?('#{voter_id}'): #{valid_voter_id?(voter_id)}"
53
+
54
+ # Both methods do the same thing
55
+ # Output:
56
+ # is_valid_voter_id('690847092828'): true
57
+ # valid_voter_id?('690847092828'): true
58
+
59
+ # ============================================================================
60
+ # SECTION 3: Invalid Formats
61
+ # ============================================================================
62
+ puts "\n3. INVALID VOTER ID FORMATS"
63
+ puts "-" * 80
64
+
65
+ invalid_voter_ids = [
66
+ ['123', 'Too short'],
67
+ ['12345678901234', 'Too long'],
68
+ ['690847092A28', 'Contains letter'],
69
+ ['690847092-28', 'Contains hyphen'],
70
+ ['6908 4709 28 28', 'Contains spaces'],
71
+ ['', 'Empty string']
72
+ ]
73
+
74
+ puts "\nInvalid voter IDs:"
75
+ invalid_voter_ids.each do |voter_id, reason|
76
+ result = is_valid_voter_id(voter_id)
77
+ puts " #{voter_id.inspect.ljust(20)} (#{reason}): #{result ? '✓ VALID' : '✗ INVALID'}"
78
+ end
79
+
80
+ # Output:
81
+ # "123" (Too short): ✗ INVALID
82
+ # "12345678901234" (Too long): ✗ INVALID
83
+ # "690847092A28" (Contains letter): ✗ INVALID
84
+ # ...
85
+
86
+ # ============================================================================
87
+ # SECTION 4: Invalid Federative Union
88
+ # ============================================================================
89
+ puts "\n4. INVALID FEDERATIVE UNION"
90
+ puts "-" * 80
91
+
92
+ puts "\nVoter IDs with invalid state codes:"
93
+ puts " 12345678 00 00 (federative union = 00): #{is_valid_voter_id('123456780000') ? '✓' : '✗'}"
94
+ puts " 12345678 29 00 (federative union = 29): #{is_valid_voter_id('123456782900') ? '✓' : '✗'}"
95
+ puts " 12345678 99 00 (federative union = 99): #{is_valid_voter_id('123456789900') ? '✓' : '✗'}"
96
+
97
+ # Output:
98
+ # 12345678 00 00 (federative union = 00): ✗
99
+ # 12345678 29 00 (federative union = 29): ✗
100
+ # 12345678 99 00 (federative union = 99): ✗
101
+
102
+ # ============================================================================
103
+ # SECTION 5: Invalid Verification Digits
104
+ # ============================================================================
105
+ puts "\n5. INVALID VERIFICATION DIGITS"
106
+ puts "-" * 80
107
+
108
+ puts "\nVoter IDs with wrong verification digits:"
109
+ puts " 690847092829 (wrong second VD):"
110
+ puts " Valid: #{is_valid_voter_id('690847092829') ? '✓' : '✗'}"
111
+
112
+ puts " 163204010921 (wrong second VD):"
113
+ puts " Valid: #{is_valid_voter_id('163204010921') ? '✓' : '✗'}"
114
+
115
+ puts " 690847092827 (wrong second VD):"
116
+ puts " Valid: #{is_valid_voter_id('690847092827') ? '✓' : '✗'}"
117
+
118
+ # Output:
119
+ # 690847092829 (wrong second VD):
120
+ # Valid: ✗
121
+
122
+ # ============================================================================
123
+ # SECTION 6: Formatting Voter IDs
124
+ # ============================================================================
125
+ puts "\n6. FORMATTING VOTER IDs"
126
+ puts "-" * 80
127
+
128
+ puts "\nFormatting valid voter IDs:"
129
+ valid_ids = ['690847092828', '163204010922', '000000000191']
130
+ valid_ids.each do |voter_id|
131
+ formatted = format_voter_id(voter_id)
132
+ puts " #{voter_id} → #{formatted}"
133
+ end
134
+
135
+ puts "\nFormatting invalid voter IDs returns nil:"
136
+ invalid_ids = ['123', '690847092829']
137
+ invalid_ids.each do |voter_id|
138
+ formatted = format_voter_id(voter_id)
139
+ puts " #{voter_id} → #{formatted.inspect}"
140
+ end
141
+
142
+ # Output:
143
+ # 690847092828 → 6908 4709 28 28
144
+ # 163204010922 → 1632 0401 09 22
145
+ # 000000000191 → 0000 0000 01 91
146
+ # 123 → nil
147
+ # 690847092829 → nil
148
+
149
+ # ============================================================================
150
+ # SECTION 7: Format Alias Method
151
+ # ============================================================================
152
+ puts "\n7. FORMAT ALIAS METHOD"
153
+ puts "-" * 80
154
+
155
+ voter_id = '690847092828'
156
+ puts "\nDifferent ways to format:"
157
+ puts " format_voter_id('#{voter_id}'): #{format_voter_id(voter_id)}"
158
+ puts " format('#{voter_id}'): #{format(voter_id)}"
159
+
160
+ # Both are the same
161
+ # Output:
162
+ # format_voter_id('690847092828'): 6908 4709 28 28
163
+ # format('690847092828'): 6908 4709 28 28
164
+
165
+ # ============================================================================
166
+ # SECTION 8: Generating Voter IDs
167
+ # ============================================================================
168
+ puts "\n8. GENERATING VOTER IDs"
169
+ puts "-" * 80
170
+
171
+ puts "\nGenerate voter IDs for specific states:"
172
+ states = ['SP', 'MG', 'RJ', 'BA', 'PR']
173
+ states.each do |uf|
174
+ voter_id = generate(uf)
175
+ formatted = format(voter_id)
176
+ state_code = voter_id[8..9]
177
+ puts " #{uf} (#{state_code}): #{formatted}"
178
+ end
179
+
180
+ # Output (random, will vary):
181
+ # SP (01): 1234 5678 01 40
182
+ # MG (02): 9876 5432 02 11
183
+ # RJ (03): 5555 5555 03 91
184
+ # ...
185
+
186
+ # ============================================================================
187
+ # SECTION 9: Generate with Default (Foreigners)
188
+ # ============================================================================
189
+ puts "\n9. GENERATE FOR FOREIGNERS (ZZ)"
190
+ puts "-" * 80
191
+
192
+ puts "\nGenerate voter ID for foreigners (default ZZ = 28):"
193
+ 3.times do |i|
194
+ voter_id = generate # Default is 'ZZ'
195
+ formatted = format(voter_id)
196
+ puts " #{i + 1}. #{formatted} (state code: #{voter_id[8..9]})"
197
+ end
198
+
199
+ # Output (random):
200
+ # 1. 5555 5555 28 01 (state code: 28)
201
+ # 2. 1234 5678 28 45 (state code: 28)
202
+ # 3. 9876 5432 28 89 (state code: 28)
203
+
204
+ # ============================================================================
205
+ # SECTION 10: Case Insensitive UF Codes
206
+ # ============================================================================
207
+ puts "\n10. CASE INSENSITIVE UF CODES"
208
+ puts "-" * 80
209
+
210
+ puts "\nGenerate with different case variations:"
211
+ ['SP', 'sp', 'Sp', 'sP'].each do |uf|
212
+ voter_id = generate(uf)
213
+ state_code = voter_id[8..9]
214
+ puts " generate('#{uf}'): state code = #{state_code}"
215
+ end
216
+
217
+ # Output:
218
+ # generate('SP'): state code = 01
219
+ # generate('sp'): state code = 01
220
+ # generate('Sp'): state code = 01
221
+ # generate('sP'): state code = 01
222
+
223
+ # ============================================================================
224
+ # SECTION 11: Invalid UF Codes Return nil
225
+ # ============================================================================
226
+ puts "\n11. INVALID UF CODES"
227
+ puts "-" * 80
228
+
229
+ puts "\nGenerating with invalid UF codes returns nil:"
230
+ invalid_ufs = ['XX', 'AB', '123', '']
231
+ invalid_ufs.each do |uf|
232
+ result = generate(uf)
233
+ puts " generate('#{uf}'): #{result.inspect}"
234
+ end
235
+
236
+ # Output:
237
+ # generate('XX'): nil
238
+ # generate('AB'): nil
239
+ # generate('123'): nil
240
+ # generate(''): nil
241
+
242
+ # ============================================================================
243
+ # SECTION 12: All Brazilian States
244
+ # ============================================================================
245
+ puts "\n12. GENERATE FOR ALL UF CODES"
246
+ puts "-" * 80
247
+
248
+ puts "\nGenerate voter IDs for all Brazilian states and territories:"
249
+ all_ufs = %w[SP MG RJ RS BA PR CE PE SC GO MA PB PA ES PI RN AL MT MS DF SE AM RO AC AP RR TO ZZ]
250
+ all_ufs.each do |uf|
251
+ voter_id = generate(uf)
252
+ uf_code = UF_CODES[uf]
253
+ puts " #{uf.ljust(2)} (#{uf_code}): #{format(voter_id)}"
254
+ end
255
+
256
+ # Output (random):
257
+ # SP (01): 1234 5678 01 40
258
+ # MG (02): 9876 5432 02 11
259
+ # RJ (03): 5555 5555 03 91
260
+ # ...
261
+ # ZZ (28): 1111 2222 28 56
262
+
263
+ # ============================================================================
264
+ # SECTION 13: Batch Validation
265
+ # ============================================================================
266
+ puts "\n13. BATCH VALIDATION"
267
+ puts "-" * 80
268
+
269
+ voter_ids_batch = [
270
+ '690847092828',
271
+ '163204010922',
272
+ '000000000191',
273
+ '123456789012',
274
+ '690847092A28',
275
+ '123',
276
+ ''
277
+ ]
278
+
279
+ valid_count = 0
280
+ invalid_count = 0
281
+
282
+ puts "\nValidating batch of voter IDs:"
283
+ voter_ids_batch.each do |voter_id|
284
+ if is_valid_voter_id(voter_id)
285
+ puts " ✓ #{format_voter_id(voter_id)}"
286
+ valid_count += 1
287
+ else
288
+ puts " ✗ #{voter_id.inspect} [INVALID]"
289
+ invalid_count += 1
290
+ end
291
+ end
292
+
293
+ puts "\nSummary:"
294
+ puts " Total: #{voter_ids_batch.length}"
295
+ puts " Valid: #{valid_count}"
296
+ puts " Invalid: #{invalid_count}"
297
+ puts " Success rate: #{(valid_count.to_f / voter_ids_batch.length * 100).round(2)}%"
298
+
299
+ # Output:
300
+ # ✓ 6908 4709 28 28
301
+ # ✓ 1632 0401 09 22
302
+ # ✓ 0000 0000 01 91
303
+ # ✗ "123456789012" [INVALID]
304
+ # ...
305
+
306
+ # ============================================================================
307
+ # SECTION 14: Voter Registration Form Validation
308
+ # ============================================================================
309
+ puts "\n14. VOTER REGISTRATION FORM VALIDATION"
310
+ puts "-" * 80
311
+
312
+ def validate_voter_registration(voter_id, name)
313
+ puts "\nValidating registration for #{name}:"
314
+ puts " Voter ID: #{voter_id}"
315
+
316
+ if voter_id.nil? || voter_id.empty?
317
+ puts " Status: ✗ REJECTED - Voter ID is required"
318
+ return false
319
+ end
320
+
321
+ unless is_valid_voter_id(voter_id)
322
+ puts " Status: ✗ REJECTED - Invalid voter ID"
323
+ return false
324
+ end
325
+
326
+ formatted = format_voter_id(voter_id)
327
+ state_code = voter_id[8..9]
328
+ puts " Formatted: #{formatted}"
329
+ puts " State code: #{state_code}"
330
+ puts " Status: ✓ APPROVED"
331
+ true
332
+ end
333
+
334
+ # Test with different inputs
335
+ validate_voter_registration('690847092828', 'João Silva')
336
+ validate_voter_registration('123456789012', 'Maria Santos')
337
+ validate_voter_registration('', 'Pedro Costa')
338
+ validate_voter_registration('163204010922', 'Ana Oliveira')
339
+
340
+ # Output:
341
+ # Validating registration for João Silva:
342
+ # Voter ID: 690847092828
343
+ # Formatted: 6908 4709 28 28
344
+ # State code: 28
345
+ # Status: ✓ APPROVED
346
+ # ...
347
+
348
+ # ============================================================================
349
+ # SECTION 15: Database Cleanup
350
+ # ============================================================================
351
+ puts "\n15. DATABASE CLEANUP SIMULATION"
352
+ puts "-" * 80
353
+
354
+ # Simulate database with voter records
355
+ database = [
356
+ { id: 1, name: 'João Silva', voter_id: '690847092828' },
357
+ { id: 2, name: 'Maria Santos', voter_id: '123456789012' },
358
+ { id: 3, name: 'Pedro Costa', voter_id: '163204010922' },
359
+ { id: 4, name: 'Ana Oliveira', voter_id: '000000000191' },
360
+ { id: 5, name: 'Carlos Souza', voter_id: '690847092A28' }
361
+ ]
362
+
363
+ puts "\nCleaning invalid voter IDs from database:"
364
+ valid_records = []
365
+ invalid_records = []
366
+
367
+ database.each do |record|
368
+ if is_valid_voter_id(record[:voter_id])
369
+ valid_records << record
370
+ puts " ✓ Record ##{record[:id]}: #{record[:name]} - #{format_voter_id(record[:voter_id])}"
371
+ else
372
+ invalid_records << record
373
+ puts " ✗ Record ##{record[:id]}: #{record[:name]} - #{record[:voter_id].inspect} [INVALID]"
374
+ end
375
+ end
376
+
377
+ puts "\nCleanup Summary:"
378
+ puts " Total records: #{database.length}"
379
+ puts " Valid records: #{valid_records.length}"
380
+ puts " Invalid records: #{invalid_records.length}"
381
+ puts " Records to remove: #{invalid_records.map { |r| "##{r[:id]}" }.join(', ')}"
382
+
383
+ # Output:
384
+ # ✓ Record #1: João Silva - 6908 4709 28 28
385
+ # ✗ Record #2: Maria Santos - "123456789012" [INVALID]
386
+ # ...
387
+
388
+ # ============================================================================
389
+ # SECTION 16: Import Validation
390
+ # ============================================================================
391
+ puts "\n16. IMPORT VALIDATION"
392
+ puts "-" * 80
393
+
394
+ # Simulate CSV import
395
+ import_data = [
396
+ { line: 1, data: 'João Silva,690847092828' },
397
+ { line: 2, data: 'Maria Santos,163204010922' },
398
+ { line: 3, data: 'Pedro Costa,123' },
399
+ { line: 4, data: 'Ana Oliveira,000000000191' },
400
+ { line: 5, data: 'Carlos Souza,690847092A28' }
401
+ ]
402
+
403
+ puts "\nValidating imported voter IDs:"
404
+ errors = []
405
+
406
+ import_data.each do |row|
407
+ name, voter_id = row[:data].split(',')
408
+
409
+ if is_valid_voter_id(voter_id)
410
+ puts " ✓ Line #{row[:line]}: #{name.ljust(20)} #{format_voter_id(voter_id)}"
411
+ else
412
+ puts " ✗ Line #{row[:line]}: #{name.ljust(20)} #{voter_id.inspect} [INVALID]"
413
+ errors << { line: row[:line], name: name, voter_id: voter_id }
414
+ end
415
+ end
416
+
417
+ if errors.empty?
418
+ puts "\n✓ Import completed successfully - all voter IDs are valid"
419
+ else
420
+ puts "\n✗ Import completed with errors:"
421
+ errors.each do |error|
422
+ puts " Line #{error[:line]}: #{error[:name]} has invalid voter ID '#{error[:voter_id]}'"
423
+ end
424
+ end
425
+
426
+ # Output:
427
+ # ✓ Line 1: João Silva 6908 4709 28 28
428
+ # ✓ Line 2: Maria Santos 1632 0401 09 22
429
+ # ✗ Line 3: Pedro Costa "123" [INVALID]
430
+ # ...
431
+
432
+ # ============================================================================
433
+ # SECTION 17: Statistics Generation
434
+ # ============================================================================
435
+ puts "\n17. VOTER ID STATISTICS"
436
+ puts "-" * 80
437
+
438
+ # Generate sample data
439
+ sample_size = 100
440
+ puts "\nGenerating #{sample_size} random voter IDs..."
441
+
442
+ state_distribution = Hash.new(0)
443
+ all_ufs = %w[SP MG RJ RS BA PR CE PE SC GO]
444
+
445
+ sample_size.times do
446
+ uf = all_ufs.sample
447
+ voter_id = generate(uf)
448
+ state_distribution[uf] += 1
449
+ end
450
+
451
+ puts "\nState Distribution:"
452
+ state_distribution.sort_by { |_uf, count| -count }.each do |uf, count|
453
+ percentage = (count.to_f / sample_size * 100).round(2)
454
+ bar = '█' * (count / 2)
455
+ puts " #{uf}: #{count.to_s.rjust(3)} (#{percentage.to_s.rjust(6)}%) #{bar}"
456
+ end
457
+
458
+ # Output (random):
459
+ # SP: 15 ( 15.00%) ███████
460
+ # MG: 12 ( 12.00%) ██████
461
+ # RJ: 11 ( 11.00%) █████
462
+ # ...
463
+
464
+ # ============================================================================
465
+ # SECTION 18: Edge Cases and Special Scenarios
466
+ # ============================================================================
467
+ puts "\n18. EDGE CASES AND SPECIAL SCENARIOS"
468
+ puts "-" * 80
469
+
470
+ puts "\nTesting edge cases:"
471
+
472
+ # All zeros (except verification digits)
473
+ test_cases = [
474
+ ['000000000191', 'Valid voter ID with zeros'],
475
+ ['548044090191', 'Voter ID with VD = 0 (rest = 10)'],
476
+ ['1234567890101', '13-digit voter ID (SP/MG edge case)']
477
+ ]
478
+
479
+ test_cases.each do |voter_id, description|
480
+ result = is_valid_voter_id(voter_id)
481
+ status = result ? '✓ VALID' : '✗ INVALID'
482
+ formatted = result ? format_voter_id(voter_id) : 'N/A'
483
+ puts " #{description}:"
484
+ puts " Input: #{voter_id}"
485
+ puts " Status: #{status}"
486
+ puts " Formatted: #{formatted}" if result
487
+ puts
488
+ end
489
+
490
+ # Output:
491
+ # Valid voter ID with zeros:
492
+ # Input: 000000000191
493
+ # Status: ✓ VALID
494
+ # Formatted: 0000 0000 01 91
495
+ # ...
496
+
497
+ # ============================================================================
498
+ # SECTION 19: UF Code Reference Table
499
+ # ============================================================================
500
+ puts "\n19. UF CODE REFERENCE TABLE"
501
+ puts "-" * 80
502
+
503
+ puts "\nComplete UF code mapping:"
504
+ puts " UF | Code | State Name"
505
+ puts " ----|------|" + ("-" * 30)
506
+
507
+ uf_names = {
508
+ 'SP' => 'São Paulo', 'MG' => 'Minas Gerais', 'RJ' => 'Rio de Janeiro',
509
+ 'RS' => 'Rio Grande do Sul', 'BA' => 'Bahia', 'PR' => 'Paraná',
510
+ 'CE' => 'Ceará', 'PE' => 'Pernambuco', 'SC' => 'Santa Catarina',
511
+ 'GO' => 'Goiás', 'MA' => 'Maranhão', 'PB' => 'Paraíba',
512
+ 'PA' => 'Pará', 'ES' => 'Espírito Santo', 'PI' => 'Piauí',
513
+ 'RN' => 'Rio Grande do Norte', 'AL' => 'Alagoas', 'MT' => 'Mato Grosso',
514
+ 'MS' => 'Mato Grosso do Sul', 'DF' => 'Distrito Federal', 'SE' => 'Sergipe',
515
+ 'AM' => 'Amazonas', 'RO' => 'Rondônia', 'AC' => 'Acre',
516
+ 'AP' => 'Amapá', 'RR' => 'Roraima', 'TO' => 'Tocantins',
517
+ 'ZZ' => 'Foreigner / Estrangeiro'
518
+ }
519
+
520
+ UF_CODES.sort_by { |_uf, code| code }.each do |uf, code|
521
+ puts " #{uf.ljust(4)}| #{code.ljust(5)}| #{uf_names[uf]}"
522
+ end
523
+
524
+ # Output:
525
+ # UF | Code | State Name
526
+ # ----|------|------------------------------
527
+ # SP | 01 | São Paulo
528
+ # MG | 02 | Minas Gerais
529
+ # RJ | 03 | Rio de Janeiro
530
+ # ...
531
+
532
+ # ============================================================================
533
+ # SECTION 20: Real-World Valid Examples
534
+ # ============================================================================
535
+ puts "\n20. REAL-WORLD VALID VOTER ID EXAMPLES"
536
+ puts "-" * 80
537
+
538
+ puts "\nKnown valid voter IDs with formatting:"
539
+ known_valid = [
540
+ '690847092828',
541
+ '163204010922',
542
+ '000000000191',
543
+ '123456780140',
544
+ '548044090191'
545
+ ]
546
+
547
+ known_valid.each_with_index do |voter_id, index|
548
+ formatted = format_voter_id(voter_id)
549
+ state_code = voter_id[8..9]
550
+ vd1 = voter_id[10]
551
+ vd2 = voter_id[11]
552
+
553
+ puts "\n Example #{index + 1}:"
554
+ puts " Raw: #{voter_id}"
555
+ puts " Formatted: #{formatted}"
556
+ puts " State: #{state_code}"
557
+ puts " VD1: #{vd1}"
558
+ puts " VD2: #{vd2}"
559
+ puts " Valid: #{is_valid_voter_id(voter_id) ? '✓ Yes' : '✗ No'}"
560
+ end
561
+
562
+ # Output:
563
+ # Example 1:
564
+ # Raw: 690847092828
565
+ # Formatted: 6908 4709 28 28
566
+ # State: 28
567
+ # VD1: 2
568
+ # VD2: 8
569
+ # Valid: ✓ Yes
570
+
571
+ puts "\n" + "=" * 80
572
+ puts "END OF EXAMPLES"
573
+ puts "=" * 80