Skip to content

Commit 9b06814

Browse files
Merge pull request #42 from brazzcore/feature/26-voter-registration-card-mock-pt-br
[feature/26] :: voter registration card mock pt br
2 parents c5f28ae + 06c5176 commit 9b06814

File tree

5 files changed

+168
-37
lines changed

5 files changed

+168
-37
lines changed

examples/mock_example.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"github.com/brazzcore/mocai/pkg/mocai/entities/company"
1010
"github.com/brazzcore/mocai/pkg/mocai/entities/person"
1111
"github.com/brazzcore/mocai/pkg/mocai/entities/phone"
12+
"github.com/brazzcore/mocai/pkg/mocai/entities/vote_registration"
1213
"github.com/brazzcore/mocai/pkg/mocai/translations"
1314
)
1415

@@ -44,6 +45,12 @@ func GenerateMockExample() {
4445
return
4546
}
4647

48+
vote_registration_mock, err := vote_registration.GenerateVoteRegistration(false)
49+
if err != nil {
50+
fmt.Print(err)
51+
return
52+
}
53+
4754
fmt.Println(constants.HeaderMain)
4855
fmt.Println(constants.SubHeader)
4956

@@ -62,5 +69,7 @@ func GenerateMockExample() {
6269
address_mock.Street, address_mock.Number, address_mock.City, address_mock.State, address_mock.UF, address_mock.ZIP)
6370
fmt.Printf("Phone: (%s) %s\n", phone_mock.AreaCode, phone_mock.Number)
6471

72+
fmt.Printf("Voter Registration Card: Section: %s, Zone: %s, Registration: %s\n", vote_registration_mock.BrazilianVoteRegistration.Section, vote_registration_mock.BrazilianVoteRegistration.Zone, vote_registration_mock.BrazilianVoteRegistration.Number)
73+
6574
fmt.Println(constants.Footer)
6675
}

pkg/mocai/entities/certificate/countries/validator.go

Lines changed: 0 additions & 37 deletions
This file was deleted.
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
package countries
2+
3+
import (
4+
"fmt"
5+
"math/rand"
6+
"strconv"
7+
"time"
8+
)
9+
10+
var (
11+
globalRand = rand.New(rand.NewSource(time.Now().UnixNano()))
12+
)
13+
14+
// BrazilianVoteRegistration represents a Brazilian vote registration.
15+
type BrazilianVoteRegistration struct {
16+
Section string
17+
Zone string
18+
Number string
19+
}
20+
21+
// GenerateBrazilianVoteRegistration generates a valid Brazilian vote registration number.
22+
// If formatted is true, the Brazilian vote registration number will be returned in the format XXX XXX XXX.
23+
// If formatted is false, the Brazilian vote registration number will be returned as a plain string.
24+
func GenerateBrazilianVoteRegistration(formatted bool) (*BrazilianVoteRegistration, error) {
25+
section := randomInt3Digits()
26+
zone := randomInt3Digits()
27+
28+
// Generate an 8 digit sequence number
29+
sequenceNumber := randomInt(1, 99999999)
30+
sequenceNumberStr := fmt.Sprintf("%08d", sequenceNumber)
31+
32+
// Generate a random state code 01 to 28
33+
stateCode := randomInt(1, 28)
34+
stateCodeStr := fmt.Sprintf("%02d", stateCode)
35+
36+
// Calculate the first check digit
37+
checkDigit1, err := calculateCheckDigit1(sequenceNumberStr)
38+
if err != nil {
39+
return nil, err
40+
}
41+
42+
// Calculate the second check digit
43+
checkDigit2, err := calculateCheckDigit2(stateCodeStr, checkDigit1, stateCode)
44+
if err != nil {
45+
return nil, err
46+
}
47+
48+
// Combine everything to form the complete number
49+
number := sequenceNumberStr + stateCodeStr + checkDigit1 + checkDigit2
50+
if number == "" || len(number) != 12 {
51+
return nil, ErrInvalidVoteRegistration
52+
}
53+
54+
if formatted {
55+
number = fmt.Sprintf("%s %s %s", number[:4], number[4:8], number[8:])
56+
}
57+
58+
createdBrazilianVoteRegistration := &BrazilianVoteRegistration{
59+
Section: section,
60+
Zone: zone,
61+
Number: number,
62+
}
63+
64+
return createdBrazilianVoteRegistration, nil
65+
}
66+
67+
// randomInt generates a random integer between min and max
68+
func randomInt(min, max int) int {
69+
return globalRand.Intn(max-min+1) + min
70+
}
71+
72+
// randomInt3Digits generates a random 3 digit number
73+
func randomInt3Digits() string {
74+
return fmt.Sprintf("%03d", globalRand.Intn(1000))
75+
}
76+
77+
// calculateCheckDigit1 calculates the first check digit.
78+
// It depends on the sequence number.
79+
func calculateCheckDigit1(sequenceNumber string) (string, error) {
80+
sum := 0
81+
weights := []int{2, 3, 4, 5, 6, 7, 8, 9}
82+
for i := 0; i < len(sequenceNumber); i++ {
83+
digit, err := strconv.Atoi(string(sequenceNumber[i]))
84+
if err != nil {
85+
return "", ErrInvalidCheckDigit1
86+
}
87+
sum += digit * weights[i]
88+
}
89+
90+
checkDigit1 := sum % 11
91+
if checkDigit1 == 10 {
92+
checkDigit1 = 0
93+
}
94+
95+
return strconv.Itoa(checkDigit1), nil
96+
}
97+
98+
// calculateCheckDigit2 calculates the second check digit.
99+
// It depends on the state code and the first check digit.
100+
func calculateCheckDigit2(stateCode, checkDigit1 string, stateCodeInt int) (string, error) {
101+
sum := 0
102+
weights := []int{7, 8}
103+
for i := 0; i < len(stateCode); i++ {
104+
digit, err := strconv.Atoi(string(stateCode[i]))
105+
if err != nil {
106+
return "", ErrInvalidCheckDigit2
107+
}
108+
sum += digit * weights[i]
109+
}
110+
checkDigit1Int, err := strconv.Atoi(checkDigit1)
111+
if err != nil {
112+
return "", ErrInvalidCheckDigit2
113+
}
114+
sum += checkDigit1Int * 9
115+
116+
checkDigit2 := sum % 11
117+
if checkDigit2 == 10 {
118+
checkDigit2 = 0
119+
}
120+
121+
// Special case for states 01 SP and 02 MG
122+
if (stateCodeInt == 1 || stateCodeInt == 2) && checkDigit2 == 0 {
123+
checkDigit2 = 1
124+
}
125+
126+
return strconv.Itoa(checkDigit2), nil
127+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package countries
2+
3+
import "errors"
4+
5+
// Errors for Vote Registration data generation failures.
6+
// These errors represent specific failure scenarios and should be wrapped with additional
7+
// context when returned.
8+
var (
9+
ErrInvalidVoteRegistration = errors.New("invalid vote registration")
10+
ErrInvalidCheckDigit1 = errors.New("invalid check digit 1")
11+
ErrInvalidCheckDigit2 = errors.New("invalid check digit 2")
12+
)
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package vote_registration
2+
3+
import "github.com/brazzcore/mocai/pkg/mocai/entities/vote_registration/countries"
4+
5+
// VoteRegistration represents a Brazilian vote registration.
6+
type VoteRegistration struct {
7+
BrazilianVoteRegistration *countries.BrazilianVoteRegistration
8+
}
9+
10+
// GenerateVoteRegistration generates a Brazilian vote registration.
11+
// If formatted is true, the Brazilian vote registration will be returned in the format XXX XXX XXX.
12+
// If formatted is false, the Brazilian vote registration will be returned as a plain string.
13+
func GenerateVoteRegistration(formatted bool) (*VoteRegistration, error) {
14+
brazilianVoteRegistration, err := countries.GenerateBrazilianVoteRegistration(formatted)
15+
if err != nil {
16+
return nil, err
17+
}
18+
19+
return &VoteRegistration{BrazilianVoteRegistration: brazilianVoteRegistration}, nil
20+
}

0 commit comments

Comments
 (0)