@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.
Files changed (46) hide show
  1. package/README.md +72 -46
  2. package/dist/index.d.ts +899 -0
  3. package/jsconfig.json +2 -2
  4. package/lib/enigma/Encoder.js +52 -18
  5. package/lib/enigma/Enigma.js +10 -9
  6. package/lib/enigma/EnigmaTypes.d.ts +17 -12
  7. package/lib/enigma/PlugBoard.js +1 -1
  8. package/lib/enigma/Reflector.js +1 -1
  9. package/lib/enigma/Rotor.js +3 -2
  10. package/lib/enigma/index.js +1 -1
  11. package/lib/enigma/tests/EnigmaSpec.js +5 -5
  12. package/lib/generator/CodeBook.js +3 -3
  13. package/lib/generator/Generator.js +5 -4
  14. package/lib/generator/GeneratorTypes.d.ts +2 -1
  15. package/lib/utils/Random.js +1 -1
  16. package/package.json +7 -2
  17. package/scripts/EnigmaData.js +236 -0
  18. package/scripts/hamlet.html +8880 -0
  19. package/scripts/make-validated-data.js +4 -0
  20. package/scripts/parseHamlet.js +32 -0
  21. package/scripts/test-messages.js +60 -0
  22. package/scripts/test.js +118 -0
  23. package/scripts/x +6446 -0
  24. package/tsconfig.json +19 -0
  25. package/types/enigma/Encoder.d.ts +128 -0
  26. package/types/enigma/Enigma.d.ts +88 -0
  27. package/types/enigma/EntryDisc.d.ts +17 -0
  28. package/types/enigma/Inventory.d.ts +91 -0
  29. package/types/enigma/PlugBoard.d.ts +26 -0
  30. package/types/enigma/Reflector.d.ts +14 -0
  31. package/types/enigma/Rotor.d.ts +59 -0
  32. package/types/enigma/consts.d.ts +1 -0
  33. package/types/enigma/index.d.ts +5 -0
  34. package/types/enigma/standardInventory.d.ts +71 -0
  35. package/types/enigma/tests/EnigmaData.d.ts +46 -0
  36. package/types/enigma/tests/EnigmaSpec.d.ts +1 -0
  37. package/types/enigma/tests/PlugBoardData.d.ts +4 -0
  38. package/types/enigma/tests/PlugBoardSpec.d.ts +1 -0
  39. package/types/enigma/tests/RotorData.d.ts +15 -0
  40. package/types/enigma/tests/RotorSpec.d.ts +1 -0
  41. package/types/generator/CodeBook.d.ts +82 -0
  42. package/types/generator/Generator.d.ts +67 -0
  43. package/types/generator/hamlet.d.ts +2 -0
  44. package/types/generator/index.d.ts +3 -0
  45. package/types/index.d.ts +899 -0
  46. package/types/utils/Random.d.ts +131 -0
package/jsconfig.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "compilerOptions": {
3
3
  "target": "es2020", // Or a newer version like "es2020"
4
- "module": "commonjs"
4
+ "module": "commonjs",
5
5
  },
6
6
  "exclude": [
7
7
  "node_modules"
8
- ]
8
+ ],
9
9
  }
@@ -133,43 +133,77 @@ export default class Encoder {
133
133
 
134
134
  /**
135
135
  *
136
- * @param {number | string} start
137
- * @param {number | string} stop
136
+ * @param {number | string} input
138
137
  * @param {Direction} direction
139
138
  */
140
- fireEncodeSet(start, stop, direction) {
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
- description: `input: ${start}`,
146
+ direction,
147
+ description: `${this.type} "${this.name}" received signal on ${input}`,
146
148
  event: 'input',
147
- input: start
149
+ input: input
148
150
  }
149
151
 
150
152
  this.fire('input', this.name, eventData);
153
+ }
151
154
 
152
- if (typeof start === 'number') start = this.connectorToLetter(start)
153
- if (typeof stop === 'number') stop = this.connectorToLetter(stop)
154
- eventData = {
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
- start,
161
- stop
168
+ description: `${this.type} "${this.name}" sent signal on ${output}`,
169
+ event: 'output',
170
+ output: output
162
171
  }
163
- this.fire('translate', this.name, eventData);
172
+ this.fire('output', this.name, eventData);
173
+ }
164
174
 
165
- eventData = {
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
- description: `output: ${stop}`,
169
- event: 'output',
170
- output: stop
189
+ direction,
190
+ description: `${this.type} "${this.name}" translated ${input} to ${output}`,
191
+ event: 'translate',
192
+ input, output
171
193
  }
172
- this.fire('output', this.name, eventData);
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
  /**
@@ -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.fireEncodeSet(letter, outputLetter, "end-to-end")
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
- encode(start, text) {
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 EncoderConfiguration {
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: EventName = "translate";
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
- start: number | string;
130
+ input: number | string;
131
131
 
132
132
  /** the translated value */
133
- stop: number | string;
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: EventName = "step";
141
+ event: "step";
142
142
 
143
143
  /** the starting rotor position */
144
- start: number | string;
144
+ start: number;
145
145
 
146
146
  /** the ending rotor position */
147
- stop: number | string
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
- eventName: EventName = "double-step",
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: EventName = "input";
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: EventName = "output";
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*/
@@ -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 {String} direction either right for moving towards the reflector or
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
@@ -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} _direction since this is the point where signal 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
  *
@@ -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 {String} direction either right for moving towards the reflector or
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: `step ${this.name}, ${this.offset} ${this.normalize(this.offset + this.ringOffset)} ${turnoverOffset} ${Boolean(turnover)}`,
106
+ description: `Rotor "${this.name}" stepped from ${start} to ${stop}${turnoverStr}`,
106
107
  event: 'step',
107
108
  turnover, start, stop
108
109
  }
@@ -1,5 +1,5 @@
1
1
  export {default as Enigma} from './Enigma.js';
2
- export {default as EntryDisc} from './EntryDisk.js';
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.encode(message.message.key,toEncode);
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.encode('AAA', 'A');
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.encode('AAV', 'A');
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.encode('ADV', 'AA');
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.encode('UZV', 'AA');
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.encode(key, start);
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.encode(start, text);
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
- options: this.enigma.configuration,
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 plugsList = Random.pickPairs(10, letters);
112
+ let plugsPairs = Random.pickPairs(10, letters);
113
113
 
114
- plugsList = plugsList.map((pair) => pair.join(""));
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.encode(start, decoded);
156
+ let encoded = enigma.translate(start, decoded);
157
157
 
158
- return {start, encoded, decoded, configuration: enigma.configuration};
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
  }
@@ -147,7 +147,7 @@ class Random {
147
147
  * two items from the list
148
148
  */
149
149
  pickPairs(count, list) {
150
- /** @type {[T, T][]} */
150
+ /** @type {T[][]} */
151
151
  let result = [];
152
152
 
153
153
  for(let idx = 0; idx < count; idx++) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ondoher/enigma",
3
- "version": "1.0.3",
4
- "description": "Enigma machine simulator implementation with tools and documentation to help you build your own.",
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
  }