Skip to content

Commit 7c53bf5

Browse files
committed
add: snils
1 parent ee133dc commit 7c53bf5

9 files changed

Lines changed: 142 additions & 39 deletions

File tree

BENCHMARKS.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
# Benchmarks
22

3+
## Notice
4+
5+
Command to update result:
6+
7+
```bash
8+
go test -benchmem -run=^$ -bench . github.com/sshaplygin/docs-code/snils >> BENCHMARKS.md
9+
```
10+
311
## BIK
412

513
```
@@ -62,3 +70,15 @@ BenchmarkGenerate-10 403179 3100 ns/op 1010 B/op 46
6270
PASS
6371
ok github.com/sshaplygin/docs-code/ogrnip 3.411s
6472
```
73+
74+
## SNILS
75+
76+
```
77+
goos: darwin
78+
goarch: arm64
79+
pkg: github.com/sshaplygin/docs-code/snils
80+
BenchmarkValidateCorrect-10 4451258 263.2 ns/op 336 B/op 5 allocs/op
81+
BenchmarkGenerate-10 1302042 895.3 ns/op 568 B/op 25 allocs/op
82+
PASS
83+
ok github.com/sshaplygin/docs-code/snils 3.768s
84+
```

README.md

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,8 @@ Status of implementation by code package:
1515
- [ ] OKATO
1616
- [ ] Generate method
1717
- [ ] Validate method
18-
- [ ] SNILS
19-
- [ ] Generate method
20-
- [x] Validate method
2118

22-
Full supported codes: BIK, INN, KPP, OGRN, OGRNIP
19+
Full supported codes: BIK, INN, KPP, OGRN, OGRNIP, SNILS
2320

2421
## Usage
2522

generate.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"github.com/sshaplygin/docs-code/kpp"
77
"github.com/sshaplygin/docs-code/ogrn"
88
"github.com/sshaplygin/docs-code/ogrnip"
9+
"github.com/sshaplygin/docs-code/snils"
910
)
1011

1112
type GenerateFunc func() string
@@ -23,6 +24,8 @@ func Generate(docType DocType) string {
2324
callFunc = ogrn.Generate
2425
case OGRNIP:
2526
callFunc = ogrnip.Generate
27+
case SNILS:
28+
callFunc = snils.Generate
2629
}
2730

2831
if callFunc == nil {

snils/models.go

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,94 @@
11
package snils
22

3+
import (
4+
"fmt"
5+
"strconv"
6+
"strings"
7+
8+
"github.com/sshaplygin/docs-code/models"
9+
"github.com/sshaplygin/docs-code/utils"
10+
)
11+
312
const packageName = "snils"
13+
14+
type Numbers []int
15+
16+
const checkSumLength = 2
17+
18+
type checkSum int
19+
20+
type SNILSStruct struct {
21+
numbers Numbers
22+
checkSum checkSum
23+
}
24+
25+
func (ss *SNILSStruct) String() string {
26+
var res strings.Builder
27+
res.Grow(snilsFullLength)
28+
29+
for i := 0; i < len(ss.numbers); i++ {
30+
if i%3 == 0 && i != 0 {
31+
res.WriteString("-")
32+
}
33+
res.WriteString(strconv.Itoa(ss.numbers[i]))
34+
}
35+
36+
res.WriteString(" ")
37+
res.WriteString(utils.StrCode(int(ss.checkSum), checkSumLength))
38+
39+
return res.String()
40+
}
41+
42+
func (ss *SNILSStruct) IsValid() (bool, error) {
43+
return ss.calculateCheckSum() == ss.checkSum, nil
44+
}
45+
46+
const (
47+
snilsFullLength = 14
48+
snilsShrinkLength = 11
49+
)
50+
51+
func ParseSNILS(snils string) (*SNILSStruct, error) {
52+
if len(snils) != snilsFullLength {
53+
return nil, &models.CommonError{
54+
Method: packageName,
55+
Err: models.ErrInvalidLength,
56+
}
57+
}
58+
59+
fSnils := strings.ReplaceAll(snils, "-", "")
60+
fSnils = strings.ReplaceAll(fSnils, " ", "")
61+
62+
if len(fSnils) != snilsShrinkLength {
63+
return nil, ErrInvalidFormattedLength
64+
}
65+
66+
snilsArr, err := utils.StrToArr(fSnils)
67+
if err != nil {
68+
return nil, fmt.Errorf("parse raw %s: %w", packageName, err)
69+
}
70+
71+
return &SNILSStruct{
72+
numbers: Numbers(snilsArr[:len(snilsArr)-2]),
73+
checkSum: checkSum(utils.SliceToInt(snilsArr[len(snilsArr)-2:])),
74+
}, nil
75+
}
76+
77+
func NewSNILS() *SNILSStruct {
78+
data := &SNILSStruct{
79+
numbers: Numbers(utils.CodeToInts(int(utils.RandomDigits(9)))),
80+
}
81+
82+
data.checkSum = data.calculateCheckSum()
83+
84+
return data
85+
}
86+
87+
func (ss *SNILSStruct) calculateCheckSum() checkSum {
88+
var hashSum int
89+
for i, v := range ss.numbers {
90+
hashSum += v * (len(ss.numbers) - i)
91+
}
92+
93+
return checkSum(hashSum % 101 % 100)
94+
}

snils/snils.go

Lines changed: 5 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,21 @@
11
package snils
22

33
import (
4-
"strconv"
5-
"strings"
6-
7-
"github.com/sshaplygin/docs-code/models"
8-
"github.com/sshaplygin/docs-code/utils"
4+
"fmt"
95
)
106

117
// Validate check to valid SNILS format
128
// example: input format is 112-233-445 95
139
func Validate(snils string) (bool, error) {
14-
if len(snils) != 14 {
15-
return false, &models.CommonError{
16-
Method: packageName,
17-
Err: models.ErrInvalidLength,
18-
}
19-
}
20-
21-
fSnils := strings.ReplaceAll(snils, "-", "")
22-
fSnils = strings.ReplaceAll(fSnils, " ", "")
23-
24-
if len(fSnils) != 11 {
25-
return false, ErrInvalidFormattedLength
26-
}
27-
28-
snilsArr, err := utils.StrToArr(fSnils)
10+
snilsData, err := ParseSNILS(snils)
2911
if err != nil {
30-
return false, err
31-
}
32-
33-
hashSum := 0
34-
hashLen := len(fSnils) - 2
35-
code, _ := strconv.Atoi(fSnils[hashLen:])
36-
for i, v := range snilsArr[:hashLen] {
37-
hashSum += v * (hashLen - i)
12+
return false, fmt.Errorf("parse %s model: %w", packageName, err)
3813
}
3914

40-
return hashSum%101 == code, nil
15+
return snilsData.IsValid()
4116
}
4217

4318
// Generate generate random
4419
func Generate() string {
45-
panic("not implemented!")
20+
return NewSNILS().String()
4621
}

snils/snils_test.go

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,6 @@ func TestValidate(t *testing.T) {
7575
},
7676
{
7777
Code: "112-233-445 98",
78-
Error: nil,
7978
IsValid: false,
8079
},
8180
{
@@ -85,7 +84,6 @@ func TestValidate(t *testing.T) {
8584
},
8685
{
8786
Code: "112-233-445 95",
88-
Error: nil,
8987
IsValid: true,
9088
},
9189
{
@@ -109,7 +107,22 @@ func TestValidate(t *testing.T) {
109107
}
110108

111109
func Test_Generate(t *testing.T) {
112-
require.Panics(t, func() {
110+
for i := 0; i < 10; i++ {
111+
snils := Generate()
112+
isValid, err := Validate(snils)
113+
require.NoError(t, err, fmt.Sprintf("invalid ogrnip value: %s", snils))
114+
115+
assert.True(t, isValid)
116+
}
117+
}
118+
119+
func BenchmarkValidateCorrect(b *testing.B) {
120+
for i := 0; i < b.N; i++ {
121+
_, _ = Validate("112-233-445 95")
122+
}
123+
}
124+
func BenchmarkGenerate(b *testing.B) {
125+
for i := 0; i < b.N; i++ {
113126
Generate()
114-
})
127+
}
115128
}

types.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@ const (
88
KPP
99
OGRN
1010
OGRNIP
11+
SNILS
1112
)

utils/helpers.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ func StrCode(val, length int) string {
8181

8282
n := length
8383
if len(code) > length {
84-
panic(fmt.Sprintf("invalid int code length: %d, %d", len(code), length))
84+
panic(fmt.Sprintf("invalid int code '%s' length: %d, %d", code, len(code), length))
8585
}
8686

8787
str.Grow(n)

validate.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"github.com/sshaplygin/docs-code/kpp"
77
"github.com/sshaplygin/docs-code/ogrn"
88
"github.com/sshaplygin/docs-code/ogrnip"
9+
"github.com/sshaplygin/docs-code/snils"
910
)
1011

1112
type ValidateFunc func(code string) (bool, error)
@@ -23,6 +24,8 @@ func Validate(docType DocType, code string) (bool, error) {
2324
callFunc = ogrn.Validate
2425
case OGRNIP:
2526
callFunc = ogrnip.Validate
27+
case SNILS:
28+
callFunc = snils.Validate
2629
}
2730

2831
if callFunc == nil {

0 commit comments

Comments
 (0)