/
damm.ts
63 lines (53 loc) · 1.67 KB
/
damm.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
/**
* cdigit
*
* @copyright 2018-2023 LiosK
* @license (MIT OR Apache-2.0)
*/
import type { CdigitAlgo } from "../type.js";
class Damm implements CdigitAlgo {
constructor(readonly name: string, readonly longName: string) {}
/** The Damm operation table. */
private readonly opTable = [
[0, 3, 1, 7, 5, 9, 8, 6, 4, 2],
[7, 0, 9, 2, 1, 5, 4, 8, 6, 3],
[4, 2, 0, 6, 8, 7, 1, 3, 5, 9],
[1, 7, 5, 0, 9, 8, 3, 4, 2, 6],
[6, 1, 2, 3, 0, 4, 5, 9, 7, 8],
[3, 6, 7, 4, 2, 0, 9, 5, 8, 1],
[5, 8, 6, 9, 7, 2, 0, 1, 3, 4],
[8, 9, 4, 5, 3, 6, 2, 0, 1, 7],
[9, 4, 3, 8, 6, 1, 7, 2, 0, 5],
[2, 5, 8, 1, 4, 3, 6, 7, 9, 0],
];
computeFromNumVals(ns: number[]): number[] {
if (ns.length === 0) {
throw new SyntaxError("string to be protected is empty");
} else if (ns.some((e) => e < 0 || e > 9 || !Number.isInteger(e))) {
throw new SyntaxError("invalid numerical value detected");
}
return [ns.reduce((c, e) => this.opTable[c][e], 0)];
}
compute(s: string): string {
const ds = String(s).replace(/[^0-9]/g, "");
const ns = [...ds].map(Number);
return String(this.computeFromNumVals(ns)[0]);
}
parse(s: string): [string, string] {
const m = String(s).match(/^(.*)([0-9])$/s);
if (m != null) {
return [m[1], m[2]];
} else {
throw new SyntaxError("could not find check character(s)");
}
}
generate(s: string): string {
return `${s}${this.compute(s)}`;
}
validate(s: string): boolean {
const [bare, cc] = this.parse(s);
return this.compute(bare) === cc;
}
}
/** The Damm algorithm implementation. */
export const damm: CdigitAlgo = new Damm("damm", "Damm Algorithm");