Created
June 14, 2021 18:40
-
-
Save skinofstars/ac0860b81654b5a321982e1451f28207 to your computer and use it in GitHub Desktop.
USPS Traditional ACS keyline MOD 10 check digit
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const keylinesChecks: [string, number][] = [ | |
['JLSTMS6796', 9], | |
['TMS1112/62', 3], | |
['218XN91LMS', 4], | |
['OTUBIKALAM', 8], | |
['ABC999NN//3', 2], | |
['ANIT 028', 1], | |
['0012 ////', 8], | |
['811N IS00 0111', 9], | |
['OTUB IKAL AM', 8], | |
['SEIR AMT', 4], | |
['1402 4981 49', 0], | |
['AEIO UW', 0], | |
['1234 5678 90', 7], | |
['DCS1 402', 0], | |
['0987 6543 21', 3], | |
]; | |
describe.each(keylinesChecks)('Creating a keyline check digit', (input, expected) => { | |
it(`should produce check digit ${expected} for keyline ${input}`, () => { | |
expect(getUSPSKeylineCheckDigit(input)).toEqual(expected); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const RADIX_DECIMAL = 10; | |
const RADIX_HEX = 16; | |
const isNumber = (n: string): boolean => !isNaN(parseInt(n, RADIX_DECIMAL)); | |
// Convert ascii characters to numeric values by zeroing out all but the lower four bits | |
const acsCharToInt = (c: string): number => | |
parseInt(c.charCodeAt(0).toString(RADIX_HEX).slice(-1), RADIX_HEX); | |
const isOdd = (n: number): boolean => n % 2 === 1; | |
// Reduce by summing figures until single figure | |
const sumDoubleDigits = (n: number): number => { | |
if (n < 10) return n; | |
const [a, b] = n | |
.toString() | |
.split('') | |
.map((v) => parseInt(v, RADIX_DECIMAL)); | |
return sumDoubleDigits(a + b); | |
}; | |
const lastFigure = (n: number): number => | |
parseInt(n.toString().split('').slice(-1).join(), RADIX_DECIMAL); | |
/** | |
* For generating a USPS Traditional ACS keyline check digit | |
* https://postalpro.usps.com/mnt/glusterfs/2019-10/TraditionalACSTechnicalGuide.pdf | |
* | |
* @param keyline A string for our own reference | |
* @returns USPS ACS Traditional keyline MOD 10 check digit | |
*/ | |
export function getUSPSKeylineCheckDigit(keyline: string) { | |
const keySum = keyline | |
// Remove whitespace | |
.replace(/\s+/g, '') | |
.split('') | |
// Convert any letters to ACS defined numerical equivalent | |
.map((val) => (isNumber(val) ? parseInt(val, RADIX_DECIMAL) : acsCharToInt(val))) | |
// Multiply odd position keys by weighting factor of 2 ... a.k.a. double it | |
.map((val, idx) => (isOdd(idx + 1) ? val * 2 : val)) | |
// Reduce double to single digits | |
.map((val) => sumDoubleDigits(val)) | |
// Sum | |
.reduce((a, b) => a + b, 0); | |
// so we don't subtract 0 from 10 | |
if (lastFigure(keySum) === 0) return 0; | |
return 10 - lastFigure(keySum); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment