Skip to content

Commit 7d91dc2

Browse files
author
Dmitry Ovsyanko
committed
+randomINN12
1 parent 4e06fa6 commit 7d91dc2

12 files changed

+215
-183
lines changed

__tests__/digit.js

-8
This file was deleted.

__tests__/isINN12.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
const {isINN12} = require ('..')
1+
const {isINN12, randomINN12} = require ('..')
22

33
test ('basic', () => {
44

55
expect (() => isINN12 ('423543534553')).toThrow ()
66
expect (() => isINN12 ('635277570473')).toThrow ()
77

88
expect (isINN12 ('635277570478')).toBeUndefined ()
9+
expect (isINN12 (randomINN12 ())).toBeUndefined ()
910

1011
})

__tests__/isKPP.js

+3
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ const {isKPP, randomKPP} = require ('..')
22

33
test ('basic', () => {
44

5+
expect (() => isKPP (771401001)).toThrow ()
56
expect (() => isKPP ('7714010011')).toThrow ()
7+
expect (() => isKPP ('7714010O1')).toThrow ()
8+
expect (() => isKPP ('7714010?1')).toThrow ()
69

710
expect (isKPP ('771401001')).toBeUndefined ()
811

__tests__/isOGRN13.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
const {isOGRN13, randomOGRN13} = require ('..')
22

33
test ('basic', () => {
4-
4+
55
expect (() => isOGRN13 ('5060049620796')).toThrow ()
66
expect (() => isOGRN13 ('6160094236029')).toThrow ()
77
expect (() => isOGRN13 ('1027700280938')).toThrow ()

__tests__/scalarProduct.js

-12
This file was deleted.

index.js

+19-160
Original file line numberDiff line numberDiff line change
@@ -1,171 +1,30 @@
1-
const COEF_SNILS = new Uint8Array ([9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0])
2-
const COEF_INN_10 = new Uint8Array ([2, 4, 10, 3, 5, 9, 4, 6, 8, 0])
3-
const COEF_KPP = new Uint8Array ([0, 0, 0, 0, 0, 0, 0, 0, 0])
4-
const COEF_INN_12_1 = new Uint8Array ([7, 2, 4, 10, 3, 5, 9, 4, 6, 8, 0, 0])
5-
const COEF_INN_12_2 = new Uint8Array ([3, 7, 2, 4, 10, 3, 5, 9, 4, 6, 8, 0])
6-
const COEF_OGRN_13 = [
7-
100000000000,
8-
10000000000,
9-
1000000000,
10-
100000000,
11-
10000000,
12-
1000000,
13-
100000,
14-
10000,
15-
1000,
16-
100,
17-
10,
18-
1,
19-
0
20-
]
21-
22-
const COEF_OGRN_15 = [
23-
10000000000000,
24-
1000000000000,
25-
100000000000,
26-
10000000000,
27-
1000000000,
28-
100000000,
29-
10000000,
30-
1000000,
31-
100000,
32-
10000,
33-
1000,
34-
100,
35-
10,
36-
1,
37-
0
38-
]
39-
40-
const die = (s, o) => {
41-
42-
const err = Error (s)
43-
44-
for (const k in o) err [k] = o [k]
45-
46-
throw err
47-
48-
}
49-
50-
const digit = (str, pos) => str.charCodeAt (pos) & 15
51-
52-
const scalarProduct = (coef, str) => {
53-
54-
if (typeof str !== 'string') die ('Arg 1 must be string', {code: 'type', type: typeof str})
55-
56-
const {length} = coef; if (length !== str.length) die ('Invalid length', {code: 'length', tobe: length, asis: str.length})
57-
58-
const buf = Buffer.from (str)
59-
60-
let s = 0; for (let i = 0; i < length; i ++) {
61-
62-
let dec = buf [i]; if ((dec & 16) !== 16) die ('Not a digit', {code: 'char', pos: i, value: str.charAt (i)})
63-
64-
dec &= 15; if (dec > 9) die ('Not a digit', {code: 'char', pos: i, value: str.charAt (i)})
65-
66-
const k = coef [i]; if (k === 0) continue
67-
68-
s += k * dec
69-
70-
}
71-
72-
return s
73-
74-
}
75-
76-
const randomString = length => {
77-
78-
const b = Buffer.alloc (length)
79-
80-
for (let i = 0; i < length; i ++) b [i] = 48 + Math.floor (10 * Math.random ())
81-
82-
return b.toString ()
83-
84-
}
85-
86-
const is1011 = (str, COEF) => {
87-
88-
const tobe = scalarProduct (COEF, str) % 11 % 10, asis = digit (str, COEF.length - 1)
89-
90-
if (tobe !== asis) die ('Wrong checksum', {code: 'checksum', tobe, asis})
91-
92-
}
93-
94-
const random1011 = COEF => {
95-
96-
const
97-
length = COEF.length - 1,
98-
no = randomString (length)
99-
100-
return no + scalarProduct (COEF.slice (0, length), no) % 11 % 10
101-
102-
}
1+
const Check = require ('./lib/Check')
2+
const {OGRN_13, OGRN_15} = require ('./lib/Horner')
3+
const {INN_10, INN_12_2, INN_12_1} = require ('./lib/INN')
4+
const SNILS = require ('./lib/SNILS')
5+
class KPP extends Check {constructor () {super (9)}}
1036

1047
module.exports = {
1058

106-
digit,
107-
scalarProduct,
9+
isSNILS : str => new SNILS ().verify (str),
10+
randomSNILS : options => new SNILS ().random (options),
10811

109-
isINN12: str => {
110-
111-
{
112-
113-
const tobe = scalarProduct (COEF_INN_12_1, str) % 11 % 10, asis = digit (str, 10)
12+
isOGRN15 : str => new OGRN_15 ().verify (str),
13+
randomOGRN15: () => new OGRN_15 ().random (),
11414

115-
if (tobe !== asis) die ('Wrong checksum', {code: 'checksum', tobe, asis, phase: 1})
116-
117-
}
15+
isOGRN13 : str => new OGRN_13 ().verify (str),
16+
randomOGRN13: () => new OGRN_13 ().random (),
11817

119-
{
18+
isINN10 : str => new INN_10 ().verify (str),
19+
randomINN10 : () => new INN_10 ().random (),
12020

121-
const tobe = scalarProduct (COEF_INN_12_2, str) % 11 % 10, asis = digit (str, 11)
122-
123-
if (tobe !== asis) die ('Wrong checksum', {code: 'checksum', tobe, asis, phase: 2})
124-
125-
}
126-
127-
},
128-
129-
isKPP: str => {scalarProduct (COEF_KPP, str)},
130-
randomKPP: () => randomString (COEF_KPP.length),
131-
132-
isINN10: str => is1011 (str, COEF_INN_10),
133-
randomINN10: () => random1011 (COEF_INN_10),
134-
135-
isOGRN13: str => is1011 (str, COEF_OGRN_13),
136-
randomOGRN13: () => random1011 (COEF_OGRN_13),
137-
138-
isOGRN15: str => is1011 (str, COEF_OGRN_15),
139-
randomOGRN15: () => random1011 (COEF_OGRN_15),
140-
141-
isSNILS: str => {
142-
143-
if (str.length === 14) {
144-
145-
if (str.charCodeAt (3) !== 45) die ('Wrong format', {code: 'format', pos: 3})
146-
if (str.charCodeAt (7) !== 45) die ('Wrong format', {code: 'format', pos: 7})
147-
if (str.charCodeAt (11) !== 32) die ('Wrong format', {code: 'format', pos: 11})
148-
149-
str = str.slice (0, 3) + str.slice (4, 7) + str.slice (8, 11) + str.slice (12)
150-
151-
}
152-
153-
const tobe = scalarProduct (COEF_SNILS, str) % 101 % 100, asis = 10 * digit (str, 9) + digit (str, 10)
154-
155-
if (tobe !== asis) die ('Wrong checksum', {code: 'checksum', tobe, asis})
156-
157-
},
158-
159-
randomSNILS: (options = {}) => {
160-
161-
const
162-
length = COEF_SNILS.length - 2,
163-
no = randomString (length),
164-
sum = scalarProduct (COEF_SNILS.slice (0, length), no) % 101 % 100
165-
result = sum < 10 ? no + '0' + sum : no + sum
166-
167-
return !options.format ? result : result.slice (0, 3) + '-' + result.slice (3, 6) + '-' + result.slice (6, 9) + ' ' + result.slice (9)
21+
isKPP : str => new KPP ().process (str),
22+
randomKPP : () => new KPP ().randomValue (),
16823

24+
isINN12: str => {
25+
new INN_12_1 ().verify (str.slice (0, 11))
26+
new INN_12_2 ().verify (str)
16927
},
28+
randomINN12: () => new INN_12_2 ().appendCheckSum (new INN_12_1 ().random ())
17029

17130
}

lib/Check.js

+95
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
module.exports = class {
2+
3+
constructor (totalLength, checkSumLength = 0) {
4+
5+
this.valueLength = totalLength - checkSumLength
6+
this.checkSumLength = checkSumLength
7+
this.totalLength = totalLength
8+
9+
}
10+
11+
raise (s, o) {
12+
13+
const err = Error (s)
14+
15+
for (const k in o) err [k] = o [k]
16+
17+
throw err
18+
19+
}
20+
21+
processDigit (pos, digit) {
22+
23+
// nothing
24+
25+
}
26+
27+
process (str, checkAllDigits) {
28+
29+
if (typeof str !== 'string') this.raise ('Arg 1 must be string', {code: 'type', type: typeof str})
30+
31+
const length = checkAllDigits ? this.totalLength : this.valueLength
32+
33+
if (length !== str.length) this.raise ('Invalid length', {code: 'length', tobe: length, asis: str.length})
34+
35+
for (let i = 0; i < length; i ++) {
36+
37+
let dec = str.charCodeAt (i); if ((dec & 16) !== 16) this.raise ('Not a digit', {code: 'char', pos: i, value: str.charAt (i)})
38+
39+
dec &= 15; if (dec > 9) this.raise ('Not a digit', {code: 'char', pos: i, value: str.charAt (i)})
40+
41+
if (i < this.valueLength) this.processDigit (i, dec)
42+
43+
}
44+
45+
}
46+
47+
randomValue () {
48+
49+
const {valueLength} = this, b = Buffer.alloc (this.valueLength)
50+
51+
for (let i = 0; i < valueLength; i ++) b [i] = 48 + Math.floor (10 * Math.random ())
52+
53+
return b.toString ()
54+
55+
}
56+
57+
checkSum (str, checkAllDigits = false) {
58+
59+
this.sum = 0
60+
61+
this.process (str, checkAllDigits)
62+
63+
const {sum} = this; delete this.sum
64+
65+
return String (this.checkSumLength === 1 ? sum % 11 % 10 : sum % 101 % 100)
66+
67+
.padStart (this.checkSumLength, '0')
68+
69+
}
70+
71+
verify (str) {
72+
73+
const tobe = this.checkSum (str, true), asis = str.slice (this.valueLength)
74+
75+
if (tobe === asis) return
76+
77+
this.raise ('Wrong checksum', {code: 'checksum', tobe, asis})
78+
79+
}
80+
81+
appendCheckSum (str) {
82+
83+
return str + this.checkSum (str)
84+
85+
}
86+
87+
random () {
88+
89+
const v = this.randomValue ()
90+
91+
return this.appendCheckSum (v)
92+
93+
}
94+
95+
}

lib/Horner.js

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
const Check = require ('./Check')
2+
3+
class Horner extends Check {
4+
5+
constructor (totalLength) {
6+
7+
super (totalLength, 1)
8+
9+
}
10+
11+
processDigit (pos, digit) {
12+
13+
this.sum *= 10
14+
15+
this.sum += digit
16+
17+
}
18+
19+
}
20+
21+
const horner = length => class OGRN_15 extends Horner {constructor () {super (length)}}
22+
23+
module.exports = {
24+
OGRN_13: horner (13),
25+
OGRN_15: horner (15),
26+
}

lib/INN.js

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
const ScalarProduct = require ('./ScalarProduct')
2+
3+
const COEF = new Uint8Array ([3, 7, 2, 4, 10, 3, 5, 9, 4, 6, 8])
4+
5+
const inn = skip => class extends ScalarProduct {constructor () {super (COEF.slice (skip))}}
6+
7+
module.exports = {
8+
9+
INN_10 : inn (2),
10+
INN_12_1 : inn (1),
11+
INN_12_2 : inn (0),
12+
13+
}

0 commit comments

Comments
 (0)