85 lines
2.0 KiB
TypeScript
85 lines
2.0 KiB
TypeScript
import {
|
|
buildReflectors,
|
|
buildRotors,
|
|
ReflectorValues,
|
|
RotorValues,
|
|
} from "./loadComponentData";
|
|
import { Plugboard } from "./plugboard";
|
|
import { Rotor } from "./rotors";
|
|
import { checkCharacter } from "./validation";
|
|
|
|
const rotors = buildRotors("rotors.csv");
|
|
const reflectors = buildReflectors("reflectors.csv");
|
|
|
|
export class Machine {
|
|
plugboard: Plugboard;
|
|
reflector: ReflectorValues;
|
|
rotors: Rotor[];
|
|
|
|
constructor(reflector: string, first: string, second: string, third: string) {
|
|
this.plugboard = new Plugboard();
|
|
this.reflector = getComponent(reflectors, reflector);
|
|
|
|
this.rotors = [];
|
|
this.rotors.push(getRotor(getComponent(rotors, first)));
|
|
this.rotors.push(getRotor(getComponent(rotors, second)));
|
|
this.rotors.push(getRotor(getComponent(rotors, third)));
|
|
}
|
|
|
|
rings(): string[] {
|
|
return this.rotors.map((r) => r.position());
|
|
}
|
|
|
|
stecker(one: string, two: string) {
|
|
this.plugboard.stecker(one, two);
|
|
}
|
|
|
|
input(message: string): string {
|
|
let output = "";
|
|
for (let char of message) {
|
|
checkCharacter(char, "character");
|
|
let turnover = true;
|
|
|
|
// plugboard, first pass
|
|
let scrambled = this.plugboard.in(char);
|
|
|
|
// rotors, first pass (in)
|
|
for (const rotor of this.rotors) {
|
|
if (turnover) {
|
|
turnover = rotor.rotate();
|
|
}
|
|
|
|
scrambled = rotor.in(scrambled);
|
|
}
|
|
|
|
// reflector
|
|
scrambled = this.reflector.reflector.get(scrambled)!;
|
|
|
|
// rotors, second pass (out)
|
|
for (let i = this.rotors.length - 1; i >= 0; i--) {
|
|
const rotor = this.rotors[i];
|
|
scrambled = rotor.out(scrambled);
|
|
}
|
|
|
|
// plugboard, second pass
|
|
output += this.plugboard.in(scrambled);
|
|
}
|
|
|
|
return output;
|
|
}
|
|
}
|
|
|
|
function getRotor({ name, values, turnovers }: RotorValues) {
|
|
return new Rotor(name, values, turnovers, 0);
|
|
}
|
|
|
|
function getComponent<T extends { name: string }>(
|
|
components: T[],
|
|
componentName: string,
|
|
): T {
|
|
const component = components.find(({ name }) => name === componentName);
|
|
if (!component) throw new Error(`unknown reflector: ${component}`);
|
|
|
|
return component;
|
|
}
|