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.
- checksums.yaml +7 -0
- data/.gitignore +120 -0
- data/.rspec +2 -0
- data/.travis.yml +5 -0
- data/Gemfile +3 -0
- data/LICENSE.txt +21 -0
- data/README.md +348 -0
- data/Rakefile +6 -0
- data/examples/boleto_usage_example.rb +79 -0
- data/examples/cep_usage_example.rb +148 -0
- data/examples/cnh_usage_example.rb +120 -0
- data/examples/cnpj_usage_example.rb +227 -0
- data/examples/cpf_usage_example.rb +237 -0
- data/examples/currency_usage_example.rb +266 -0
- data/examples/date_usage_example.rb +259 -0
- data/examples/email_usage_example.rb +321 -0
- data/examples/legal_nature_usage_example.rb +437 -0
- data/examples/legal_process_usage_example.rb +444 -0
- data/examples/license_plate_usage_example.rb +440 -0
- data/examples/phone_usage_example.rb +595 -0
- data/examples/pis_usage_example.rb +588 -0
- data/examples/renavam_usage_example.rb +499 -0
- data/examples/voter_id_usage_example.rb +573 -0
- data/lib/brazilian-utils/boleto-utils.rb +176 -0
- data/lib/brazilian-utils/cep-utils.rb +330 -0
- data/lib/brazilian-utils/cnh-utils.rb +88 -0
- data/lib/brazilian-utils/cnpj-utils.rb +202 -0
- data/lib/brazilian-utils/cpf-utils.rb +192 -0
- data/lib/brazilian-utils/currency-utils.rb +226 -0
- data/lib/brazilian-utils/data/legal_process_ids.json +38 -0
- data/lib/brazilian-utils/date-utils.rb +244 -0
- data/lib/brazilian-utils/email-utils.rb +54 -0
- data/lib/brazilian-utils/legal-nature-utils.rb +235 -0
- data/lib/brazilian-utils/legal-process-utils.rb +240 -0
- data/lib/brazilian-utils/license-plate-utils.rb +279 -0
- data/lib/brazilian-utils/phone-utils.rb +272 -0
- data/lib/brazilian-utils/pis-utils.rb +151 -0
- data/lib/brazilian-utils/renavam-utils.rb +113 -0
- data/lib/brazilian-utils/voter-id-utils.rb +165 -0
- 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
|