@ondoher/enigma 1.0.3 → 1.0.6
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.
- package/README.md +72 -46
- package/dist/index.d.ts +899 -0
- package/jsconfig.json +2 -2
- package/lib/enigma/Encoder.js +52 -18
- package/lib/enigma/Enigma.js +10 -9
- package/lib/enigma/EnigmaTypes.d.ts +17 -12
- package/lib/enigma/PlugBoard.js +1 -1
- package/lib/enigma/Reflector.js +1 -1
- package/lib/enigma/Rotor.js +3 -2
- package/lib/enigma/index.js +1 -1
- package/lib/enigma/tests/EnigmaSpec.js +5 -5
- package/lib/generator/CodeBook.js +3 -3
- package/lib/generator/Generator.js +5 -4
- package/lib/generator/GeneratorTypes.d.ts +2 -1
- package/lib/utils/Random.js +1 -1
- package/package.json +7 -2
- package/scripts/EnigmaData.js +236 -0
- package/scripts/hamlet.html +8880 -0
- package/scripts/make-validated-data.js +4 -0
- package/scripts/parseHamlet.js +32 -0
- package/scripts/test-messages.js +60 -0
- package/scripts/test.js +118 -0
- package/scripts/x +6446 -0
- package/tsconfig.json +19 -0
- package/types/enigma/Encoder.d.ts +128 -0
- package/types/enigma/Enigma.d.ts +88 -0
- package/types/enigma/EntryDisc.d.ts +17 -0
- package/types/enigma/Inventory.d.ts +91 -0
- package/types/enigma/PlugBoard.d.ts +26 -0
- package/types/enigma/Reflector.d.ts +14 -0
- package/types/enigma/Rotor.d.ts +59 -0
- package/types/enigma/consts.d.ts +1 -0
- package/types/enigma/index.d.ts +5 -0
- package/types/enigma/standardInventory.d.ts +71 -0
- package/types/enigma/tests/EnigmaData.d.ts +46 -0
- package/types/enigma/tests/EnigmaSpec.d.ts +1 -0
- package/types/enigma/tests/PlugBoardData.d.ts +4 -0
- package/types/enigma/tests/PlugBoardSpec.d.ts +1 -0
- package/types/enigma/tests/RotorData.d.ts +15 -0
- package/types/enigma/tests/RotorSpec.d.ts +1 -0
- package/types/generator/CodeBook.d.ts +82 -0
- package/types/generator/Generator.d.ts +67 -0
- package/types/generator/hamlet.d.ts +2 -0
- package/types/generator/index.d.ts +3 -0
- package/types/index.d.ts +899 -0
- package/types/utils/Random.d.ts +131 -0
package/jsconfig.json
CHANGED
package/lib/enigma/Encoder.js
CHANGED
|
@@ -133,43 +133,77 @@ export default class Encoder {
|
|
|
133
133
|
|
|
134
134
|
/**
|
|
135
135
|
*
|
|
136
|
-
* @param {number | string}
|
|
137
|
-
* @param {number | string} stop
|
|
136
|
+
* @param {number | string} input
|
|
138
137
|
* @param {Direction} direction
|
|
139
138
|
*/
|
|
140
|
-
|
|
139
|
+
fireInput(input, direction) {
|
|
140
|
+
if (typeof input === 'number') input = this.connectorToLetter(input)
|
|
141
|
+
|
|
141
142
|
/** @type {EventData} */
|
|
142
143
|
let eventData = {
|
|
143
144
|
name: this.name,
|
|
144
145
|
type: this.type,
|
|
145
|
-
|
|
146
|
+
direction,
|
|
147
|
+
description: `${this.type} "${this.name}" received signal on ${input}`,
|
|
146
148
|
event: 'input',
|
|
147
|
-
input:
|
|
149
|
+
input: input
|
|
148
150
|
}
|
|
149
151
|
|
|
150
152
|
this.fire('input', this.name, eventData);
|
|
153
|
+
}
|
|
151
154
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
+
/**
|
|
156
|
+
*
|
|
157
|
+
* @param {number | string} output
|
|
158
|
+
* @param {Direction} direction
|
|
159
|
+
*/
|
|
160
|
+
fireOutput(output, direction) {
|
|
161
|
+
if (typeof output === 'number') output = this.connectorToLetter(output)
|
|
162
|
+
|
|
163
|
+
/** @type {EventData} */
|
|
164
|
+
let eventData = {
|
|
155
165
|
name: this.name,
|
|
156
166
|
type: this.type,
|
|
157
|
-
description: `${this.type}: ${this.name} translate ${start} to ${stop}`,
|
|
158
|
-
event: 'translate',
|
|
159
167
|
direction,
|
|
160
|
-
|
|
161
|
-
|
|
168
|
+
description: `${this.type} "${this.name}" sent signal on ${output}`,
|
|
169
|
+
event: 'output',
|
|
170
|
+
output: output
|
|
162
171
|
}
|
|
163
|
-
this.fire('
|
|
172
|
+
this.fire('output', this.name, eventData);
|
|
173
|
+
}
|
|
164
174
|
|
|
165
|
-
|
|
175
|
+
/**
|
|
176
|
+
*
|
|
177
|
+
* @param {number | string} input
|
|
178
|
+
* @param {number | string} output
|
|
179
|
+
* @param {Direction} direction
|
|
180
|
+
*/
|
|
181
|
+
fireTranslate(input, output, direction) {
|
|
182
|
+
if (typeof input === 'number') input = this.connectorToLetter(input)
|
|
183
|
+
if (typeof output === 'number') output = this.connectorToLetter(output)
|
|
184
|
+
|
|
185
|
+
/** @type {EventData} */
|
|
186
|
+
let eventData = {
|
|
166
187
|
name: this.name,
|
|
167
188
|
type: this.type,
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
189
|
+
direction,
|
|
190
|
+
description: `${this.type} "${this.name}" translated ${input} to ${output}`,
|
|
191
|
+
event: 'translate',
|
|
192
|
+
input, output
|
|
171
193
|
}
|
|
172
|
-
this.fire('
|
|
194
|
+
this.fire('translate', this.name, eventData);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
*
|
|
199
|
+
* @param {number | string} input
|
|
200
|
+
* @param {number | string} output
|
|
201
|
+
* @param {Direction} direction
|
|
202
|
+
*/
|
|
203
|
+
fireEncodeSet(input, output, direction) {
|
|
204
|
+
this.fireInput(input, direction);
|
|
205
|
+
this.fireOutput(output, direction);
|
|
206
|
+
this.fireTranslate(input, output, direction);
|
|
173
207
|
}
|
|
174
208
|
|
|
175
209
|
/**
|
package/lib/enigma/Enigma.js
CHANGED
|
@@ -37,7 +37,7 @@ export default class Enigma extends Encoder {
|
|
|
37
37
|
/** @type {Encoder[]} */
|
|
38
38
|
this.encoders = [];
|
|
39
39
|
/**@type {SimplifiedConfiguration & {reflector: string}} */
|
|
40
|
-
this._configuration = {reflector}
|
|
40
|
+
this._configuration = {reflector, ringSettings: [], rotors: [], plugs: ''};
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
/**
|
|
@@ -107,13 +107,13 @@ export default class Enigma extends Encoder {
|
|
|
107
107
|
|
|
108
108
|
this._configuration = {...this._configuration,
|
|
109
109
|
rotors,
|
|
110
|
-
ringOffsets,
|
|
110
|
+
ringSettings: ringOffsets,
|
|
111
111
|
plugs: this.plugboard.plugs
|
|
112
112
|
}
|
|
113
113
|
}
|
|
114
114
|
|
|
115
115
|
/**
|
|
116
|
-
* Call this method to step the rotors one time. This method will manage the
|
|
116
|
+
* Call this method to "step" the rotors one time. This method will manage the
|
|
117
117
|
* stepping between all rotors
|
|
118
118
|
*/
|
|
119
119
|
step() {
|
|
@@ -126,9 +126,10 @@ export default class Enigma extends Encoder {
|
|
|
126
126
|
/** @type {EventData} */
|
|
127
127
|
let eventData = {
|
|
128
128
|
name: rotor.name,
|
|
129
|
+
description: `rotor ${rotor.name} double stepping from ${rotor.offset}`,
|
|
130
|
+
type: this.type,
|
|
129
131
|
event: "double-step",
|
|
130
132
|
offset: rotor.offset,
|
|
131
|
-
description: `rotor ${rotor.name} double stepping from ${rotor.offset}`
|
|
132
133
|
}
|
|
133
134
|
|
|
134
135
|
this.fire('double-step', rotor.name, eventData);
|
|
@@ -166,8 +167,7 @@ export default class Enigma extends Encoder {
|
|
|
166
167
|
start = setup;
|
|
167
168
|
}
|
|
168
169
|
|
|
169
|
-
start = [...start].reverse();
|
|
170
|
-
|
|
170
|
+
start = [...start].reverse().join('');
|
|
171
171
|
// reset the rotation pending state
|
|
172
172
|
this.pending = {0: true};
|
|
173
173
|
|
|
@@ -190,7 +190,7 @@ export default class Enigma extends Encoder {
|
|
|
190
190
|
}
|
|
191
191
|
|
|
192
192
|
let connector = this.letterToConnector(letter);
|
|
193
|
-
|
|
193
|
+
this.fireInput(letter, "right");
|
|
194
194
|
this.step();
|
|
195
195
|
|
|
196
196
|
// encode to the right
|
|
@@ -210,7 +210,8 @@ export default class Enigma extends Encoder {
|
|
|
210
210
|
|
|
211
211
|
const outputLetter = this.connectorToLetter(connector);
|
|
212
212
|
|
|
213
|
-
this.
|
|
213
|
+
this.fireOutput(outputLetter, "left");
|
|
214
|
+
this.fireTranslate(letter, outputLetter, "end-to-end");
|
|
214
215
|
return outputLetter;
|
|
215
216
|
}
|
|
216
217
|
|
|
@@ -222,7 +223,7 @@ export default class Enigma extends Encoder {
|
|
|
222
223
|
*
|
|
223
224
|
* @returns {String} the encoded string.
|
|
224
225
|
*/
|
|
225
|
-
|
|
226
|
+
translate(start, text) {
|
|
226
227
|
this.setStart(start)
|
|
227
228
|
let letters = [...text];
|
|
228
229
|
let output = letters.map(function(letter) {
|
|
@@ -20,7 +20,7 @@ interface EncoderSetup {
|
|
|
20
20
|
* Defines how the enigma hardware is constructed. These are the settings that
|
|
21
21
|
* cannot be changed
|
|
22
22
|
*/
|
|
23
|
-
interface EnigmaSetup extends
|
|
23
|
+
interface EnigmaSetup extends EncoderSetup {
|
|
24
24
|
/** which entry disc is part of the machine, defaults to "default" */
|
|
25
25
|
entryDisc?: string;
|
|
26
26
|
/** which reflector is part of the machine */
|
|
@@ -121,16 +121,16 @@ type EventBase = {
|
|
|
121
121
|
*/
|
|
122
122
|
type TranslateData = {
|
|
123
123
|
/** the event name */
|
|
124
|
-
event:
|
|
124
|
+
event: "translate";
|
|
125
125
|
|
|
126
126
|
/** the direction the signal was sent */
|
|
127
127
|
direction: Direction;
|
|
128
128
|
|
|
129
129
|
/** the starting value */
|
|
130
|
-
|
|
130
|
+
input: number | string;
|
|
131
131
|
|
|
132
132
|
/** the translated value */
|
|
133
|
-
|
|
133
|
+
output: number | string;
|
|
134
134
|
}
|
|
135
135
|
|
|
136
136
|
/**
|
|
@@ -138,21 +138,20 @@ type TranslateData = {
|
|
|
138
138
|
*/
|
|
139
139
|
type StepData = {
|
|
140
140
|
/** the event name */
|
|
141
|
-
event:
|
|
141
|
+
event: "step";
|
|
142
142
|
|
|
143
143
|
/** the starting rotor position */
|
|
144
|
-
start: number
|
|
144
|
+
start: number;
|
|
145
145
|
|
|
146
146
|
/** the ending rotor position */
|
|
147
|
-
stop: number
|
|
147
|
+
stop: number;
|
|
148
148
|
|
|
149
149
|
/** the locations of the turnover points for this rotor */
|
|
150
150
|
turnover: boolean;
|
|
151
151
|
}
|
|
152
152
|
|
|
153
153
|
type DoubleStepData = {
|
|
154
|
-
|
|
155
|
-
rotor: string;
|
|
154
|
+
event: "double-step",
|
|
156
155
|
offset: number;
|
|
157
156
|
}
|
|
158
157
|
|
|
@@ -161,10 +160,13 @@ type DoubleStepData = {
|
|
|
161
160
|
*/
|
|
162
161
|
type InputData = {
|
|
163
162
|
/** the event name */
|
|
164
|
-
event:
|
|
163
|
+
event: "input";
|
|
165
164
|
|
|
166
165
|
/** the input connection */
|
|
167
166
|
input: number | string;
|
|
167
|
+
|
|
168
|
+
/** the direction the signal was sent */
|
|
169
|
+
direction: Direction;
|
|
168
170
|
}
|
|
169
171
|
|
|
170
172
|
/**
|
|
@@ -172,14 +174,17 @@ type InputData = {
|
|
|
172
174
|
*/
|
|
173
175
|
type OutputData = {
|
|
174
176
|
/** the event name */
|
|
175
|
-
event:
|
|
177
|
+
event: "output";
|
|
176
178
|
|
|
177
179
|
/** the output connection */
|
|
178
180
|
output: number | string;
|
|
181
|
+
|
|
182
|
+
/** the direction the signal was sent */
|
|
183
|
+
direction: Direction;
|
|
179
184
|
}
|
|
180
185
|
|
|
181
186
|
/** Defines the discriminated union for all the event data */
|
|
182
|
-
type EventData = EventBase & (TranslateData | StepData | InputData | OutputData);
|
|
187
|
+
type EventData = EventBase & (TranslateData | StepData | InputData | OutputData | DoubleStepData);
|
|
183
188
|
|
|
184
189
|
type Listener = (
|
|
185
190
|
/** name of the event being fired*/
|
package/lib/enigma/PlugBoard.js
CHANGED
|
@@ -57,7 +57,7 @@ export default class PlugBoard extends Encoder {
|
|
|
57
57
|
* Call this method to convert the input connector number to the output in
|
|
58
58
|
* the given direction.
|
|
59
59
|
*
|
|
60
|
-
* @param {
|
|
60
|
+
* @param {Direction} direction either right for moving towards the reflector or
|
|
61
61
|
* left if moving back
|
|
62
62
|
* @param {Number} input the input connector
|
|
63
63
|
* @returns {Number} the output connector
|
package/lib/enigma/Reflector.js
CHANGED
|
@@ -24,7 +24,7 @@ export default class Reflector extends Encoder {
|
|
|
24
24
|
* the point where direction changes this does not have a distinction
|
|
25
25
|
* between a left and right signal path.
|
|
26
26
|
*
|
|
27
|
-
* @param {Direction}
|
|
27
|
+
* @param {Direction} direction since this is the point where signal direction
|
|
28
28
|
* changes from right to left this parameter is not used.
|
|
29
29
|
* @param {Number} input this is the input connector
|
|
30
30
|
*
|
package/lib/enigma/Rotor.js
CHANGED
|
@@ -59,7 +59,7 @@ export default class Rotor extends Encoder {
|
|
|
59
59
|
* connector for the rotor's zero point we need to adjust the connector
|
|
60
60
|
* number for the current rotation.
|
|
61
61
|
*
|
|
62
|
-
* @param {
|
|
62
|
+
* @param {Direction} direction either right for moving towards the reflector or
|
|
63
63
|
* left if moving back
|
|
64
64
|
* @param {Number} input the connector in physical space
|
|
65
65
|
*
|
|
@@ -97,12 +97,13 @@ export default class Rotor extends Encoder {
|
|
|
97
97
|
|
|
98
98
|
// turnover happens when we step past the turnover point
|
|
99
99
|
let turnover = this._turnovers.has(this.normalize(turnoverOffset - 1));
|
|
100
|
+
let turnoverStr = turnover ? 'with turnover' : ''
|
|
100
101
|
|
|
101
102
|
/** @type {EventData} */
|
|
102
103
|
let eventData = {
|
|
103
104
|
name: this.name,
|
|
104
105
|
type: this.type,
|
|
105
|
-
description: `
|
|
106
|
+
description: `Rotor "${this.name}" stepped from ${start} to ${stop}${turnoverStr}`,
|
|
106
107
|
event: 'step',
|
|
107
108
|
turnover, start, stop
|
|
108
109
|
}
|
package/lib/enigma/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export {default as Enigma} from './Enigma.js';
|
|
2
|
-
export {default as EntryDisc} from './
|
|
2
|
+
export {default as EntryDisc} from './EntryDisc.js';
|
|
3
3
|
export {default as inventory} from './Inventory.js';
|
|
4
4
|
export {default as PlugBoard} from './PlugBoard.js';
|
|
5
5
|
export {default as Reflector} from './Rotor.js';
|
|
@@ -21,7 +21,7 @@ describe('Enigma Test Cases', function() {
|
|
|
21
21
|
})
|
|
22
22
|
|
|
23
23
|
var toEncode = message.message[which]
|
|
24
|
-
var encoded = enigma.
|
|
24
|
+
var encoded = enigma.translate(message.message.key,toEncode);
|
|
25
25
|
|
|
26
26
|
return cb(message, encoded);
|
|
27
27
|
})
|
|
@@ -50,7 +50,7 @@ describe('Enigma Test Cases', function() {
|
|
|
50
50
|
|
|
51
51
|
it ('should step only the right-most rotor when not at turnover', function() {
|
|
52
52
|
steps = {};
|
|
53
|
-
enigma.
|
|
53
|
+
enigma.translate('AAA', 'A');
|
|
54
54
|
var stepped = Object.keys(steps);
|
|
55
55
|
expect(stepped.length).toBe(1);
|
|
56
56
|
expect(stepped[0]).toBe('III');
|
|
@@ -58,13 +58,13 @@ describe('Enigma Test Cases', function() {
|
|
|
58
58
|
|
|
59
59
|
it ('should step the next rotor when the previous turns over', function() {
|
|
60
60
|
steps = {};
|
|
61
|
-
enigma.
|
|
61
|
+
enigma.translate('AAV', 'A');
|
|
62
62
|
expect(steps['II'].length).toBe(1);
|
|
63
63
|
});
|
|
64
64
|
|
|
65
65
|
it ('should double step when reaching the turn over', function() {
|
|
66
66
|
steps = {};
|
|
67
|
-
enigma.
|
|
67
|
+
enigma.translate('ADV', 'AA');
|
|
68
68
|
expect(steps['II'].length).toBe(2);
|
|
69
69
|
});
|
|
70
70
|
|
|
@@ -75,7 +75,7 @@ describe('Enigma Test Cases', function() {
|
|
|
75
75
|
|
|
76
76
|
listen();
|
|
77
77
|
|
|
78
|
-
enigma.
|
|
78
|
+
enigma.translate('UZV', 'AA');
|
|
79
79
|
expect(steps['VI'].length).toBe(1);
|
|
80
80
|
});
|
|
81
81
|
})
|
|
@@ -108,11 +108,11 @@ export default class CodeBook {
|
|
|
108
108
|
|
|
109
109
|
let key = Random.choose(3, [...STANDARD_ALPHABET]).join('');
|
|
110
110
|
let start = Random.choose(3, [...STANDARD_ALPHABET]).join('');
|
|
111
|
-
let enc = this.enigma.
|
|
111
|
+
let enc = this.enigma.translate(key, start);
|
|
112
112
|
let clear = text;
|
|
113
113
|
|
|
114
114
|
text = text.replace(/ /g, '');
|
|
115
|
-
text = this.enigma.
|
|
115
|
+
text = this.enigma.translate(start, text);
|
|
116
116
|
text = this.generator.groupText(text);
|
|
117
117
|
text = paddedIndicator + ' ' + text
|
|
118
118
|
|
|
@@ -155,7 +155,7 @@ export default class CodeBook {
|
|
|
155
155
|
});
|
|
156
156
|
|
|
157
157
|
return {
|
|
158
|
-
|
|
158
|
+
configuration: this.enigma.configuration,
|
|
159
159
|
parts: messages
|
|
160
160
|
}
|
|
161
161
|
}
|
|
@@ -109,9 +109,9 @@ export default class Generator {
|
|
|
109
109
|
let useRotors = structuredClone(setup.rotors || unfixed);
|
|
110
110
|
let rotors = Random.pick(3, useRotors);
|
|
111
111
|
let ringSettings = Random.choose(3, connectors);
|
|
112
|
-
let
|
|
112
|
+
let plugsPairs = Random.pickPairs(10, letters);
|
|
113
113
|
|
|
114
|
-
plugsList =
|
|
114
|
+
let plugsList = plugsPairs.map((pair) => pair.join(""));
|
|
115
115
|
|
|
116
116
|
ringSettings[0]++;
|
|
117
117
|
ringSettings[1]++;
|
|
@@ -153,8 +153,9 @@ export default class Generator {
|
|
|
153
153
|
let decoded = this.cleanMessage(this.generateSentences(count));
|
|
154
154
|
let start = Random.choose(enigma.rotors.length, [...STANDARD_ALPHABET]).join('');
|
|
155
155
|
|
|
156
|
-
let encoded = enigma.
|
|
156
|
+
let encoded = enigma.translate(start, decoded);
|
|
157
157
|
|
|
158
|
-
return {start, encoded, decoded,
|
|
158
|
+
return {start, encoded, decoded,
|
|
159
|
+
configuration: enigma.configuration};
|
|
159
160
|
}
|
|
160
161
|
}
|
|
@@ -89,12 +89,13 @@ type GeneratedMessage = {
|
|
|
89
89
|
encoded: string;
|
|
90
90
|
/** the decoded string */
|
|
91
91
|
decoded: string;
|
|
92
|
+
configuration?: SimplifiedConfiguration;
|
|
92
93
|
}
|
|
93
94
|
|
|
94
95
|
type Model = ("I" | "M3" | "M4");
|
|
95
96
|
|
|
96
97
|
type ModelOptions = {
|
|
97
98
|
rotors: string[];
|
|
98
|
-
fixed: string[];
|
|
99
|
+
fixed: string[] | boolean;
|
|
99
100
|
reflectors: string[];
|
|
100
101
|
}
|
package/lib/utils/Random.js
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ondoher/enigma",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "Enigma machine simulator
|
|
3
|
+
"version": "1.0.6",
|
|
4
|
+
"description": "Enigma machine simulator with tools and documentation to help you build your own.",
|
|
5
5
|
"main": "./lib/index.js",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"test": "jasmine"
|
|
@@ -25,7 +25,12 @@
|
|
|
25
25
|
"homepage": "https://github.com/Ondoher/enigma#readme",
|
|
26
26
|
"type": "module",
|
|
27
27
|
"devDependencies": {
|
|
28
|
+
"@types/node": "^25.0.10",
|
|
28
29
|
"jasmine": "^4.5.0",
|
|
29
30
|
"jasmine-console-reporter": "^3.1.0"
|
|
31
|
+
},
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"@types/jasmine": "^4.6.6",
|
|
34
|
+
"undici-types": "^7.19.0"
|
|
30
35
|
}
|
|
31
36
|
}
|