puzzle-lib 1.3.0 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (180) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +38 -39
  3. package/build/src/Braille/BrailleCharacter.d.ts +15 -15
  4. package/build/src/Braille/BrailleCharacter.js +38 -37
  5. package/build/src/Braille/BrailleCharacter.js.map +1 -1
  6. package/build/src/Braille/BrailleData.d.ts +6 -6
  7. package/build/src/Braille/BrailleData.js +65 -64
  8. package/build/src/Braille/BrailleData.js.map +1 -1
  9. package/build/src/Braille/BrailleDot.d.ts +9 -9
  10. package/build/src/Braille/BrailleDot.js +13 -12
  11. package/build/src/Braille/BrailleDot.js.map +1 -1
  12. package/build/src/Braille/BrailleEncoding.d.ts +54 -54
  13. package/build/src/Braille/BrailleEncoding.js +65 -64
  14. package/build/src/Braille/BrailleEncoding.js.map +1 -1
  15. package/build/src/Braille/BrailleStream.d.ts +18 -18
  16. package/build/src/Braille/BrailleStream.js +75 -74
  17. package/build/src/Braille/BrailleStream.js.map +1 -1
  18. package/build/src/Cipher/AutoKeyString.d.ts +4 -4
  19. package/build/src/Cipher/AutoKeyString.js +34 -33
  20. package/build/src/Cipher/AutoKeyString.js.map +1 -1
  21. package/build/src/Cipher/CaesarString.d.ts +8 -8
  22. package/build/src/Cipher/CaesarString.js +31 -30
  23. package/build/src/Cipher/CaesarString.js.map +1 -1
  24. package/build/src/Cipher/CaesarUtils.d.ts +13 -13
  25. package/build/src/Cipher/CaesarUtils.js +57 -56
  26. package/build/src/Cipher/CaesarUtils.js.map +1 -1
  27. package/build/src/Cipher/KeyedCipherStringBase.d.ts +12 -12
  28. package/build/src/Cipher/KeyedCipherStringBase.js +28 -27
  29. package/build/src/Cipher/KeyedCipherStringBase.js.map +1 -1
  30. package/build/src/Cipher/VigenereString.d.ts +4 -4
  31. package/build/src/Cipher/VigenereString.js +21 -20
  32. package/build/src/Cipher/VigenereString.js.map +1 -1
  33. package/build/src/Common/CharacterImage.d.ts +6 -6
  34. package/build/src/Common/CharacterImage.js +10 -9
  35. package/build/src/Common/CharacterImage.js.map +1 -1
  36. package/build/src/Common/EncodingCategory.d.ts +8 -8
  37. package/build/src/Common/EncodingCategory.js +12 -11
  38. package/build/src/Common/EncodingCategory.js.map +1 -1
  39. package/build/src/Common/EncodingCharacterBase.d.ts +23 -23
  40. package/build/src/Common/EncodingCharacterBase.js +52 -51
  41. package/build/src/Common/EncodingCharacterBase.js.map +1 -1
  42. package/build/src/Common/EncodingDataBase.d.ts +7 -7
  43. package/build/src/Common/EncodingDataBase.js +29 -28
  44. package/build/src/Common/EncodingDataBase.js.map +1 -1
  45. package/build/src/Common/EncodingEntry.d.ts +8 -8
  46. package/build/src/Common/EncodingEntry.js +14 -13
  47. package/build/src/Common/EncodingEntry.js.map +1 -1
  48. package/build/src/Common/EncodingLookupResult.d.ts +6 -6
  49. package/build/src/Common/EncodingLookupResult.js +13 -12
  50. package/build/src/Common/EncodingLookupResult.js.map +1 -1
  51. package/build/src/Common/Helpers.d.ts +4 -4
  52. package/build/src/Common/Helpers.js +16 -15
  53. package/build/src/Common/Helpers.js.map +1 -1
  54. package/build/src/Common/InlineSvg.d.ts +7 -7
  55. package/build/src/Common/InlineSvg.js +14 -13
  56. package/build/src/Common/InlineSvg.js.map +1 -1
  57. package/build/src/Conversion/CharacterAutoConvert.d.ts +10 -7
  58. package/build/src/Conversion/CharacterAutoConvert.js +88 -80
  59. package/build/src/Conversion/CharacterAutoConvert.js.map +1 -1
  60. package/build/src/Conversion/CharacterConversion.d.ts +8 -8
  61. package/build/src/Conversion/CharacterConversion.js +50 -49
  62. package/build/src/Conversion/CharacterConversion.js.map +1 -1
  63. package/build/src/Conversion/CharacterEncoding.d.ts +9 -8
  64. package/build/src/Conversion/CharacterEncoding.js +13 -11
  65. package/build/src/Conversion/CharacterEncoding.js.map +1 -1
  66. package/build/src/Conversion/CharacterTableEntry.d.ts +10 -10
  67. package/build/src/Conversion/CharacterTableEntry.js +19 -18
  68. package/build/src/Conversion/CharacterTableEntry.js.map +1 -1
  69. package/build/src/Conversion/SignificantFigures.d.ts +7 -7
  70. package/build/src/Conversion/SignificantFigures.js +50 -49
  71. package/build/src/Conversion/SignificantFigures.js.map +1 -1
  72. package/build/src/Conversion/StringAutoConvert.d.ts +6 -6
  73. package/build/src/Conversion/StringAutoConvert.js +46 -45
  74. package/build/src/Conversion/StringAutoConvert.js.map +1 -1
  75. package/build/src/Morse/MorseCharacter.d.ts +22 -22
  76. package/build/src/Morse/MorseCharacter.js +96 -95
  77. package/build/src/Morse/MorseCharacter.js.map +1 -1
  78. package/build/src/Morse/MorseData.d.ts +6 -6
  79. package/build/src/Morse/MorseData.js +70 -69
  80. package/build/src/Morse/MorseData.js.map +1 -1
  81. package/build/src/Morse/MorseEncoding.d.ts +59 -59
  82. package/build/src/Morse/MorseEncoding.js +94 -93
  83. package/build/src/Morse/MorseEncoding.js.map +1 -1
  84. package/build/src/Morse/MorseString.d.ts +10 -10
  85. package/build/src/Morse/MorseString.js +66 -65
  86. package/build/src/Morse/MorseString.js.map +1 -1
  87. package/build/src/Nato/NatoCharacter.d.ts +5 -5
  88. package/build/src/Nato/NatoCharacter.js +10 -9
  89. package/build/src/Nato/NatoCharacter.js.map +1 -1
  90. package/build/src/Nato/NatoData.d.ts +7 -7
  91. package/build/src/Nato/NatoData.js +51 -50
  92. package/build/src/Nato/NatoData.js.map +1 -1
  93. package/build/src/NavalFlags/NavalFlags.d.ts +7 -7
  94. package/build/src/NavalFlags/NavalFlags.js +52 -50
  95. package/build/src/NavalFlags/NavalFlags.js.map +1 -1
  96. package/build/src/Resistor/Resistor.d.ts +24 -24
  97. package/build/src/Resistor/Resistor.js +86 -85
  98. package/build/src/Resistor/Resistor.js.map +1 -1
  99. package/build/src/Resistor/ResistorColorEntry.d.ts +12 -12
  100. package/build/src/Resistor/ResistorColorEntry.js +31 -30
  101. package/build/src/Resistor/ResistorColorEntry.js.map +1 -1
  102. package/build/src/Semaphore/SemaphoreCharacter.d.ts +20 -20
  103. package/build/src/Semaphore/SemaphoreCharacter.js +75 -74
  104. package/build/src/Semaphore/SemaphoreCharacter.js.map +1 -1
  105. package/build/src/Semaphore/SemaphoreData.d.ts +6 -6
  106. package/build/src/Semaphore/SemaphoreData.js +53 -52
  107. package/build/src/Semaphore/SemaphoreData.js.map +1 -1
  108. package/build/src/Semaphore/SemaphoreDegrees.d.ts +5 -5
  109. package/build/src/Semaphore/SemaphoreDegrees.js +26 -25
  110. package/build/src/Semaphore/SemaphoreDegrees.js.map +1 -1
  111. package/build/src/Semaphore/SemaphoreDirection.d.ts +11 -11
  112. package/build/src/Semaphore/SemaphoreDirection.js +15 -14
  113. package/build/src/Semaphore/SemaphoreDirection.js.map +1 -1
  114. package/build/src/Semaphore/SemaphoreEncoding.d.ts +40 -40
  115. package/build/src/Semaphore/SemaphoreEncoding.js +47 -46
  116. package/build/src/Semaphore/SemaphoreEncoding.js.map +1 -1
  117. package/build/src/Semaphore/SemaphoreStream.d.ts +17 -17
  118. package/build/src/Semaphore/SemaphoreStream.js +72 -71
  119. package/build/src/Semaphore/SemaphoreStream.js.map +1 -1
  120. package/build/src/WordSearch/Point.d.ts +4 -4
  121. package/build/src/WordSearch/Point.js +2 -2
  122. package/build/src/WordSearch/Result.d.ts +6 -6
  123. package/build/src/WordSearch/Result.js +10 -9
  124. package/build/src/WordSearch/Result.js.map +1 -1
  125. package/build/src/WordSearch/WordSearchDirection.d.ts +6 -6
  126. package/build/src/WordSearch/WordSearchDirection.js +10 -9
  127. package/build/src/WordSearch/WordSearchDirection.js.map +1 -1
  128. package/build/src/WordSearch/WordSearchSolver.d.ts +27 -18
  129. package/build/src/WordSearch/WordSearchSolver.js +222 -171
  130. package/build/src/WordSearch/WordSearchSolver.js.map +1 -1
  131. package/build/src/index.d.ts +35 -35
  132. package/build/src/index.js +72 -70
  133. package/build/src/index.js.map +1 -1
  134. package/package.json +40 -39
  135. package/src/Braille/BrailleCharacter.ts +49 -0
  136. package/src/Braille/BrailleData.ts +131 -0
  137. package/src/Braille/BrailleDot.ts +9 -0
  138. package/src/Braille/BrailleEncoding.ts +144 -0
  139. package/src/Braille/BrailleStream.ts +87 -0
  140. package/src/Cipher/AutoKeyString.ts +35 -0
  141. package/src/Cipher/CaesarString.ts +38 -0
  142. package/src/Cipher/CaesarUtils.ts +69 -0
  143. package/src/Cipher/KeyedCipherStringBase.ts +35 -0
  144. package/src/Cipher/VigenereString.ts +21 -0
  145. package/src/Common/CharacterImage.ts +11 -0
  146. package/src/Common/EncodingCategory.ts +10 -0
  147. package/src/Common/EncodingCharacterBase.ts +72 -0
  148. package/src/Common/EncodingDataBase.ts +31 -0
  149. package/src/Common/EncodingEntry.ts +17 -0
  150. package/src/Common/EncodingLookupResult.ts +10 -0
  151. package/src/Common/Helpers.ts +13 -0
  152. package/src/Common/InlineSvg.ts +15 -0
  153. package/src/Conversion/CharacterAutoConvert.ts +108 -0
  154. package/src/Conversion/CharacterConversion.ts +89 -0
  155. package/src/Conversion/CharacterEncoding.ts +9 -0
  156. package/src/Conversion/CharacterTableEntry.ts +23 -0
  157. package/src/Conversion/SignificantFigures.ts +55 -0
  158. package/src/Conversion/StringAutoConvert.ts +56 -0
  159. package/src/Morse/MorseCharacter.ts +112 -0
  160. package/src/Morse/MorseData.ts +143 -0
  161. package/src/Morse/MorseEncoding.ts +98 -0
  162. package/src/Morse/MorseString.ts +106 -0
  163. package/src/Nato/NatoCharacter.ts +9 -0
  164. package/src/Nato/NatoData.ts +49 -0
  165. package/src/NavalFlags/LICENSE +7 -0
  166. package/src/NavalFlags/NavalFlags.ts +293 -0
  167. package/src/Resistor/Resistor.ts +135 -0
  168. package/src/Resistor/ResistorColorEntry.ts +43 -0
  169. package/src/Semaphore/SemaphoreCharacter.ts +107 -0
  170. package/src/Semaphore/SemaphoreData.ts +58 -0
  171. package/src/Semaphore/SemaphoreDegrees.ts +26 -0
  172. package/src/Semaphore/SemaphoreDirection.ts +11 -0
  173. package/src/Semaphore/SemaphoreEncoding.ts +48 -0
  174. package/src/Semaphore/SemaphoreStream.ts +89 -0
  175. package/src/WordSearch/Point.ts +4 -0
  176. package/src/WordSearch/Result.ts +10 -0
  177. package/src/WordSearch/WordSearchDirection.ts +6 -0
  178. package/src/WordSearch/WordSearchSolver.ts +271 -0
  179. package/src/index.ts +38 -0
  180. package/src/trie-prefix-tree.d.ts +70 -0
@@ -0,0 +1,87 @@
1
+ import {EncodingCategory} from '../Common/EncodingCategory';
2
+ import {BrailleCharacter} from './BrailleCharacter';
3
+ import {BrailleData} from './BrailleData';
4
+ import {BrailleEncoding} from './BrailleEncoding';
5
+
6
+ export class BrailleStream {
7
+ private readonly _chars: BrailleEncoding[] = [];
8
+ private _currentStr = '';
9
+ private _processPosition = 0;
10
+ private _numberMode = false;
11
+
12
+ constructor(chars?: BrailleEncoding[]) {
13
+ if (chars) {
14
+ this._chars = Array.from(chars);
15
+ }
16
+
17
+ this.invalidate();
18
+ }
19
+
20
+ get chars() {
21
+ return this._chars;
22
+ }
23
+
24
+ set chars(value: BrailleEncoding[]) {
25
+ this.clear();
26
+
27
+ for (const ch of value) {
28
+ this._chars.push(ch);
29
+ }
30
+ }
31
+
32
+ append(ch: BrailleCharacter) {
33
+ this._chars.push(ch.valueOf());
34
+ }
35
+
36
+ clear() {
37
+ this._chars.length = 0;
38
+ this.invalidate();
39
+ }
40
+
41
+ backspace() {
42
+ this._chars.pop();
43
+ this.invalidate();
44
+ }
45
+
46
+ space() {
47
+ this._chars.push(BrailleEncoding.None);
48
+ }
49
+
50
+ toString() {
51
+ this.update();
52
+ return this._currentStr;
53
+ }
54
+
55
+ private invalidate() {
56
+ this._currentStr = '';
57
+ this._processPosition = 0;
58
+ this._numberMode = false;
59
+ }
60
+
61
+ private update() {
62
+ while (this._processPosition < this._chars.length) {
63
+ const ch = this._chars[this._processPosition];
64
+
65
+ if (ch === BrailleEncoding.None) {
66
+ this._numberMode = false;
67
+ this._currentStr += ' ';
68
+ } else if (ch === BrailleEncoding.FormattingNumber) {
69
+ this._numberMode = true;
70
+ this._currentStr += '#';
71
+ } else {
72
+ const category =
73
+ EncodingCategory.Punctuation |
74
+ (this._numberMode
75
+ ? EncodingCategory.Number
76
+ : EncodingCategory.Letter);
77
+ const exact = BrailleData.instance.lookup(ch, category).exact;
78
+
79
+ if (exact.length > 0) {
80
+ this._currentStr += exact[0].toString();
81
+ }
82
+ }
83
+
84
+ this._processPosition++;
85
+ }
86
+ }
87
+ }
@@ -0,0 +1,35 @@
1
+ import {CaesarUtils} from './CaesarUtils';
2
+ import {KeyedCipherStringBase} from './KeyedCipherStringBase';
3
+
4
+ export class AutoKeyString extends KeyedCipherStringBase {
5
+ protected convert(decrypt: boolean) {
6
+ if (this._key.length < 1) {
7
+ return this._text;
8
+ } else {
9
+ const rotStr = [];
10
+ let keyIndex = 0;
11
+ let fullKey = this._key;
12
+
13
+ for (const ch of this._text) {
14
+ if (CaesarUtils.isAlpha(ch)) {
15
+ const currentLetter = CaesarUtils.rotateLetterWithKey(
16
+ ch,
17
+ fullKey,
18
+ keyIndex++,
19
+ decrypt
20
+ );
21
+ rotStr.push(currentLetter);
22
+ if (decrypt) {
23
+ fullKey += currentLetter;
24
+ } else {
25
+ fullKey += ch;
26
+ }
27
+ } else {
28
+ rotStr.push(ch);
29
+ }
30
+ }
31
+
32
+ return rotStr.join('');
33
+ }
34
+ }
35
+ }
@@ -0,0 +1,38 @@
1
+ import {CaesarUtils} from './CaesarUtils';
2
+
3
+ export class CaesarString {
4
+ private _text: string;
5
+
6
+ constructor(text = '') {
7
+ this._text = text;
8
+ }
9
+
10
+ get text() {
11
+ return this._text;
12
+ }
13
+
14
+ set text(value: string) {
15
+ this._text = value;
16
+ }
17
+
18
+ getRotation(rot: number) {
19
+ const rotStr = [];
20
+
21
+ for (const ch of this._text) {
22
+ rotStr.push(CaesarUtils.rotateLetter(ch, rot));
23
+ }
24
+
25
+ return rotStr.join('');
26
+ }
27
+
28
+ getRotations() {
29
+ const rotations = [];
30
+ rotations.push(this._text);
31
+
32
+ for (let i = 1; i < 26; i++) {
33
+ rotations.push(this.getRotation(i));
34
+ }
35
+
36
+ return rotations;
37
+ }
38
+ }
@@ -0,0 +1,69 @@
1
+ import {CharacterConversion} from '../Conversion/CharacterConversion';
2
+
3
+ export class CaesarUtils {
4
+ static rotateLetter(ch: string, rot: number) {
5
+ if (ch.length !== 1) {
6
+ throw new Error('Expected a single character');
7
+ }
8
+
9
+ rot %= this.alphaLength;
10
+ if (rot < 0) {
11
+ rot += this.alphaLength;
12
+ }
13
+
14
+ const code = ch.charCodeAt(0);
15
+ let base = 0;
16
+ if (this.isLowerAlpha(code)) {
17
+ base = this.lowerA;
18
+ } else if (this.isUpperAlpha(code)) {
19
+ base = this.upperA;
20
+ } else {
21
+ return ch;
22
+ }
23
+
24
+ return String.fromCharCode(((code - base + rot) % this.alphaLength) + base);
25
+ }
26
+
27
+ static rotateLetterWithKey(
28
+ ch: string,
29
+ key: string,
30
+ keyIndex: number,
31
+ decrypt = false
32
+ ) {
33
+ if (key.length === 0) {
34
+ return ch;
35
+ }
36
+
37
+ const keyCh = this.getCharacterWithMod(key, keyIndex);
38
+ let rot = CharacterConversion.toOrdinal(keyCh) - 1;
39
+
40
+ if (decrypt) {
41
+ rot = -rot;
42
+ }
43
+
44
+ return this.rotateLetter(ch, rot);
45
+ }
46
+
47
+ static isAlpha(ch: string) {
48
+ const code = ch.charCodeAt(0);
49
+ return this.isUpperAlpha(code) || this.isLowerAlpha(code);
50
+ }
51
+
52
+ private static upperA: number = 'A'.charCodeAt(0);
53
+ private static upperZ: number = 'Z'.charCodeAt(0);
54
+ private static lowerA: number = 'a'.charCodeAt(0);
55
+ private static lowerZ: number = 'z'.charCodeAt(0);
56
+ private static alphaLength = 26;
57
+
58
+ private static getCharacterWithMod(str: string, index: number) {
59
+ return str.charAt(index % str.length);
60
+ }
61
+
62
+ private static isUpperAlpha(code: number) {
63
+ return code >= this.upperA && code <= this.upperZ;
64
+ }
65
+
66
+ private static isLowerAlpha(code: number) {
67
+ return code >= this.lowerA && code <= this.lowerZ;
68
+ }
69
+ }
@@ -0,0 +1,35 @@
1
+ export abstract class KeyedCipherStringBase {
2
+ protected _text: string;
3
+ protected _key: string;
4
+
5
+ constructor(text = '', key = '') {
6
+ this._text = text;
7
+ this._key = key;
8
+ }
9
+
10
+ get text() {
11
+ return this._text;
12
+ }
13
+
14
+ set text(value: string) {
15
+ this._text = value;
16
+ }
17
+
18
+ get key() {
19
+ return this._key;
20
+ }
21
+
22
+ set key(value: string) {
23
+ this._key = value;
24
+ }
25
+
26
+ encrypt() {
27
+ return this.convert(false);
28
+ }
29
+
30
+ decrypt() {
31
+ return this.convert(true);
32
+ }
33
+
34
+ protected abstract convert(decrypt: boolean): string;
35
+ }
@@ -0,0 +1,21 @@
1
+ import {CaesarUtils} from './CaesarUtils';
2
+ import {KeyedCipherStringBase} from './KeyedCipherStringBase';
3
+
4
+ export class VigenereString extends KeyedCipherStringBase {
5
+ protected convert(decrypt: boolean) {
6
+ const rotStr = [];
7
+ let keyIndex = 0;
8
+
9
+ for (const ch of this._text) {
10
+ if (CaesarUtils.isAlpha(ch)) {
11
+ rotStr.push(
12
+ CaesarUtils.rotateLetterWithKey(ch, this._key, keyIndex++, decrypt)
13
+ );
14
+ } else {
15
+ rotStr.push(ch);
16
+ }
17
+ }
18
+
19
+ return rotStr.join('');
20
+ }
21
+ }
@@ -0,0 +1,11 @@
1
+ import {InlineSvg} from './InlineSvg';
2
+
3
+ export class CharacterImage {
4
+ readonly character: string;
5
+ readonly image: InlineSvg;
6
+
7
+ constructor(character: string, image: InlineSvg) {
8
+ this.character = character;
9
+ this.image = image;
10
+ }
11
+ }
@@ -0,0 +1,10 @@
1
+ export enum EncodingCategory {
2
+ None,
3
+
4
+ Letter = 1 << 1,
5
+ Number = 1 << 2,
6
+ Formatting = 1 << 3,
7
+ Punctuation = 1 << 4,
8
+
9
+ All = 0xff,
10
+ }
@@ -0,0 +1,72 @@
1
+ import {EncodingCategory} from '../Common/EncodingCategory';
2
+ import {EncodingEntry} from '../Common/EncodingEntry';
3
+ import {EncodingLookupResult} from '../Common/EncodingLookupResult';
4
+ import {EncodingDataBase} from './EncodingDataBase';
5
+
6
+ export abstract class EncodingCharacterBase<T extends number> {
7
+ private _category: EncodingCategory;
8
+ private _data: EncodingDataBase<T>;
9
+ private _lookup: EncodingLookupResult<T> | null = null;
10
+
11
+ constructor(data: EncodingDataBase<T>, category: EncodingCategory) {
12
+ this._data = data;
13
+ this._category = category;
14
+ this.invalidateLookup();
15
+ }
16
+
17
+ get category() {
18
+ return this._category;
19
+ }
20
+
21
+ set category(value: EncodingCategory) {
22
+ if (this._category !== value) {
23
+ this._category = value;
24
+ this.invalidateLookup();
25
+ }
26
+ }
27
+
28
+ clear() {
29
+ this.onClear();
30
+ this.invalidateLookup();
31
+ }
32
+
33
+ empty() {
34
+ return this.onEmpty();
35
+ }
36
+
37
+ getExactMatches(): Array<EncodingEntry<T>> {
38
+ return this.ensureLookup().exact;
39
+ }
40
+
41
+ getPotentialMatches(): Array<EncodingEntry<T>> {
42
+ return this.ensureLookup().partial;
43
+ }
44
+
45
+ toString() {
46
+ return this.ensureLookup().exactString;
47
+ }
48
+
49
+ valid() {
50
+ return this.ensureLookup().exact.length > 0;
51
+ }
52
+
53
+ valueOf() {
54
+ return this.getEncoding();
55
+ }
56
+
57
+ protected invalidateLookup() {
58
+ this._lookup = null;
59
+ }
60
+
61
+ protected abstract onClear(): void;
62
+ protected abstract onEmpty(): boolean;
63
+ protected abstract getEncoding(): T;
64
+
65
+ private ensureLookup() {
66
+ if (!this._lookup) {
67
+ this._lookup = this._data.lookup(this.getEncoding(), this._category);
68
+ }
69
+
70
+ return this._lookup;
71
+ }
72
+ }
@@ -0,0 +1,31 @@
1
+ import {EncodingCategory} from './EncodingCategory';
2
+ import {EncodingEntry} from './EncodingEntry';
3
+ import {EncodingLookupResult} from './EncodingLookupResult';
4
+
5
+ export abstract class EncodingDataBase<T extends number> {
6
+ private readonly _entries: Array<EncodingEntry<T>> = [];
7
+
8
+ lookup(encoding: T, category: EncodingCategory = EncodingCategory.All) {
9
+ const result = new EncodingLookupResult<T>();
10
+
11
+ for (const entry of this._entries) {
12
+ if ((entry.category & category) !== 0) {
13
+ if (entry.encoding === encoding) {
14
+ result.exact.push(entry);
15
+ } else if ((entry.encoding & encoding) === encoding) {
16
+ result.partial.push(entry);
17
+ }
18
+ }
19
+ }
20
+
21
+ return result;
22
+ }
23
+
24
+ protected addToList(
25
+ encoding: T,
26
+ category: EncodingCategory,
27
+ display: string
28
+ ) {
29
+ this._entries.push(new EncodingEntry<T>(encoding, category, display));
30
+ }
31
+ }
@@ -0,0 +1,17 @@
1
+ import {EncodingCategory} from './EncodingCategory';
2
+
3
+ export class EncodingEntry<T> {
4
+ readonly encoding: T;
5
+ readonly category: EncodingCategory;
6
+ readonly display: string;
7
+
8
+ constructor(encoding: T, category: EncodingCategory, display: string) {
9
+ this.encoding = encoding;
10
+ this.category = category;
11
+ this.display = display;
12
+ }
13
+
14
+ toString() {
15
+ return this.display;
16
+ }
17
+ }
@@ -0,0 +1,10 @@
1
+ import {EncodingEntry} from './EncodingEntry';
2
+
3
+ export class EncodingLookupResult<T> {
4
+ readonly exact: Array<EncodingEntry<T>> = [];
5
+ readonly partial: Array<EncodingEntry<T>> = [];
6
+
7
+ get exactString() {
8
+ return this.exact.map(value => value.toString()).join('/');
9
+ }
10
+ }
@@ -0,0 +1,13 @@
1
+ export class Helpers {
2
+ static assert(condition: boolean) {
3
+ if (!condition) {
4
+ throw new Error();
5
+ }
6
+ }
7
+
8
+ static assertMsg(condition: boolean, message: string) {
9
+ if (!condition) {
10
+ throw new Error(message);
11
+ }
12
+ }
13
+ }
@@ -0,0 +1,15 @@
1
+ export class InlineSvg {
2
+ private readonly inlineSvg: string;
3
+ private readonly viewBoxWidth: number;
4
+ private readonly viewBoxHeight: number;
5
+
6
+ constructor(inlineSvg: string, viewBoxWidth: number, viewBoxHeight: number) {
7
+ this.inlineSvg = inlineSvg;
8
+ this.viewBoxWidth = viewBoxWidth;
9
+ this.viewBoxHeight = viewBoxHeight;
10
+ }
11
+
12
+ render(): string {
13
+ return `<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100%" height="100%" viewBox="0 0 ${this.viewBoxWidth} ${this.viewBoxHeight}">${this.inlineSvg}</svg>`;
14
+ }
15
+ }
@@ -0,0 +1,108 @@
1
+ import {CharacterEncoding} from './CharacterEncoding';
2
+
3
+ export class CharacterAutoConvert {
4
+ // Forced encoding can be useful when converting an entire string
5
+ // or simply dealing with binary which has no leading zeros
6
+ static convertCharacter(
7
+ input: string,
8
+ forcedCharacterEncoding?: CharacterEncoding
9
+ ) {
10
+ let encoding = null;
11
+ if (!forcedCharacterEncoding) {
12
+ encoding = this.determineCharacterEncoding(input);
13
+ } else {
14
+ encoding = forcedCharacterEncoding;
15
+ }
16
+
17
+ if (encoding === CharacterEncoding.None) {
18
+ return '';
19
+ }
20
+
21
+ // Assume that Latin characters should remain
22
+ if (encoding === CharacterEncoding.Latin) {
23
+ return input;
24
+ }
25
+
26
+ const baseTen = Number.parseInt(input, 10);
27
+ if (encoding === CharacterEncoding.Ascii) {
28
+ return CharacterAutoConvert.asciiPrintable(baseTen);
29
+ }
30
+ const asciiOffset = 64;
31
+ if (encoding === CharacterEncoding.Ordinal) {
32
+ return CharacterAutoConvert.asciiPrintable(baseTen + asciiOffset);
33
+ }
34
+
35
+ const binary = Number.parseInt(input, 2);
36
+ if (
37
+ encoding === CharacterEncoding.FiveBitBinary &&
38
+ this.appearsBinary(input)
39
+ ) {
40
+ return CharacterAutoConvert.asciiPrintable(binary + asciiOffset);
41
+ }
42
+ if (
43
+ encoding === CharacterEncoding.EightBitBinary &&
44
+ this.appearsBinary(input)
45
+ ) {
46
+ return CharacterAutoConvert.asciiPrintable(binary);
47
+ }
48
+
49
+ if (encoding === CharacterEncoding.Ternary) {
50
+ const ternary = Number.parseInt(input, 3);
51
+ return CharacterAutoConvert.asciiPrintable(ternary + asciiOffset);
52
+ }
53
+
54
+ return '';
55
+ }
56
+
57
+ static asciiPrintable(index: number) {
58
+ if (index < 32 || index > 126) {
59
+ return '';
60
+ }
61
+ return String.fromCharCode(index);
62
+ }
63
+
64
+ static determineCharacterEncoding(input: string) {
65
+ if (input.match(/[a-z]/i)) {
66
+ return CharacterEncoding.Latin;
67
+ }
68
+
69
+ const numeric = Number.parseInt(input, 10);
70
+
71
+ if (this.appearsBinary(input)) {
72
+ if (input.length === 5) {
73
+ return CharacterEncoding.FiveBitBinary;
74
+ } else if (input.length === 8 || input.length === 7) {
75
+ return CharacterEncoding.EightBitBinary;
76
+ }
77
+ }
78
+
79
+ if (this.appearsTernary(input)) {
80
+ return CharacterEncoding.Ternary;
81
+ }
82
+
83
+ if (input.length < 3 && numeric > 0 && numeric < 27) {
84
+ return CharacterEncoding.Ordinal;
85
+ }
86
+
87
+ if (numeric > 64 && numeric < 91) {
88
+ return CharacterEncoding.Ascii;
89
+ }
90
+ if (numeric > 97 && numeric < 123) {
91
+ return CharacterEncoding.Ascii;
92
+ }
93
+
94
+ return CharacterEncoding.None;
95
+ }
96
+
97
+ private static readonly BINARY_REGEX = new RegExp('^[01]+$');
98
+
99
+ private static appearsBinary(str: string): boolean {
100
+ return this.BINARY_REGEX.test(str);
101
+ }
102
+
103
+ private static readonly TERNARY_REGEX = new RegExp('^[0-2]{3}$');
104
+
105
+ private static appearsTernary(str: string): boolean {
106
+ return this.TERNARY_REGEX.test(str);
107
+ }
108
+ }
@@ -0,0 +1,89 @@
1
+ import {CharacterTableEntry} from './CharacterTableEntry';
2
+
3
+ export class CharacterConversion {
4
+ static getAsciiTable() {
5
+ const retVal: CharacterTableEntry[] = [];
6
+ CharacterConversion.addAsciiRange(
7
+ retVal,
8
+ 48,
9
+ 57,
10
+ CharacterConversion.toAscii,
11
+ 127
12
+ );
13
+ CharacterConversion.addAsciiRange(
14
+ retVal,
15
+ 65,
16
+ 90,
17
+ CharacterConversion.toAscii,
18
+ 127
19
+ );
20
+ CharacterConversion.addAsciiRange(
21
+ retVal,
22
+ 97,
23
+ 122,
24
+ CharacterConversion.toAscii,
25
+ 127
26
+ );
27
+
28
+ return retVal;
29
+ }
30
+
31
+ static getOrdinalTable() {
32
+ const retVal: CharacterTableEntry[] = [];
33
+ CharacterConversion.addAsciiRange(
34
+ retVal,
35
+ 65,
36
+ 90,
37
+ CharacterConversion.toOrdinal,
38
+ 26
39
+ );
40
+
41
+ return retVal;
42
+ }
43
+
44
+ static toAscii(ch: string) {
45
+ if (typeof ch !== 'string' || ch.length !== 1) {
46
+ throw new Error('A single character is required');
47
+ }
48
+
49
+ const ascii = ch.charCodeAt(0);
50
+ if (ascii >= 0 && ascii <= 127) {
51
+ return ascii;
52
+ }
53
+
54
+ return -1;
55
+ }
56
+
57
+ static toOrdinal(ch: string) {
58
+ if (typeof ch !== 'string' || ch.length !== 1) {
59
+ throw new Error('A single character is required');
60
+ }
61
+
62
+ const chCode = ch.charCodeAt(0);
63
+
64
+ let ordinalCode = chCode - 'a'.charCodeAt(0);
65
+ if (ordinalCode >= 0 && ordinalCode < 26) {
66
+ return ordinalCode + 1;
67
+ }
68
+
69
+ ordinalCode = chCode - 'A'.charCodeAt(0);
70
+ if (ordinalCode >= 0 && ordinalCode < 26) {
71
+ return ordinalCode + 1;
72
+ }
73
+
74
+ return -1;
75
+ }
76
+
77
+ private static addAsciiRange(
78
+ array: CharacterTableEntry[],
79
+ start: number,
80
+ end: number,
81
+ conversion: (value: string) => number,
82
+ maxValue: number
83
+ ) {
84
+ for (let i = start; i <= end; i++) {
85
+ const letter = String.fromCharCode(i);
86
+ array.push(new CharacterTableEntry(letter, conversion(letter), maxValue));
87
+ }
88
+ }
89
+ }
@@ -0,0 +1,9 @@
1
+ export enum CharacterEncoding {
2
+ None,
3
+ Latin, // A = A, B = B
4
+ Ordinal, // A = 1, B = 2
5
+ FiveBitBinary, // 00001 = A, 00010 = B
6
+ EightBitBinary, // 01100001 = A, 01100010 = B
7
+ Ascii, // 65 = A, 66 = B
8
+ Ternary, // 001 = A, 010 = C, 200 = R
9
+ }