-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcli.py
183 lines (145 loc) · 5.39 KB
/
cli.py
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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
import os
import sys
from enigma import *
from rotors import *
AVAILABLE_OPTIONS = ['rt', 'rf', 'rtp,' 'rtr,' 'pl', '-h']
class EnigmaCliMachine():
def __init__(self):
self.rotors = []
self.rotor_classes = []
self.ring_settings = [1, 1, 1]
self.rotor_positions = ['A', 'A', 'A']
self.plug_lead_mappings = []
self.reflector_cls = ARotor
self.machine = ARotor
def create_machine(self):
self.machine = EnigmaMachine(self.rotors, self.reflector, self.plug_lead_mappings)
def reset_machine(self):
self.set_rotors()
self.set_reflector()
self.machine.reset_state(self.rotors, self.reflector, self.plug_lead_mappings)
def accept_texts(self):
while True:
try:
text = input("Please enter the text to encode or 'exit' to cancel:\n")
if text == 'exit':
print('Exited')
sys.exit(os.EX_OK)
encoding = self.machine.encode_text(text.upper())
print(f'The encoding is: {encoding}')
self.reset_machine()
except KeyboardInterrupt:
print('You Interrupted')
sys.exit(os.EX_OK)
except Exception:
print('An error occured; please check that you passed the right settings')
sys.exit(os.EX_USAGE)
def print_help(self):
print("""
Welcome to the Enigma CLI client!
## Options
rt : Rotors (I, II, III, IV, V, Beta, Gamma)
rf : Reflector (A, B, C)
rtp : Rotor Starting Positions (A-Z; E.g. "A B E")
rtr : Ring Settings (1-26; E.g. "1 14 26")
pl : Plug Leads (E.g. "AB CD ES")
-h : Show help
For example:
> python3 cli.py rt="I II III" rf="C" rtr="1 14 26" rtp="A B E" pl="AC DE LH"
""")
def parse_args(self, args):
probably_valid_args = False
for arg_text in args:
if not '=' in arg_text:
print("Please input valid arguments")
return False
(key, value) = arg_text.split("=")
if key in AVAILABLE_OPTIONS:
probably_valid_args = self.parse_arg(key, value)
if probably_valid_args:
self.set_rotors()
self.set_reflector()
return probably_valid_args
def is_rotor_arg_value_valid(self, value):
print(value)
val_len = len(value)
if val_len != 3 and val_len != 4:
print('Please enter 3 or 4 values')
return False
valid_values = ['I', 'II', 'III', 'IV', 'V', 'Beta', 'Gamma']
for i in value:
if not i in valid_values:
print(f'Please enter one of the following {valid_values}')
return False
return True
def is_reflector_valid(self, value):
valid_values = ['A', 'B', 'C']
is_valid = value in valid_values
if not is_valid:
print(f'Please enter one of the following {valid_values}')
return is_valid
def is_plug_lead_mappings_valid(self, value):
return len(value) <= 10
def parse_arg(self, arg, value):
if arg == 'rt':
labels = value.split(" ")
if not self.is_rotor_arg_value_valid(labels):
return False
self.set_rotors_classes(labels)
elif arg == 'rf':
if not self.is_reflector_valid(value):
return False
self.set_reflector_cls(value)
elif arg == 'rtp':
positions = value.split(" ")
if not self.is_rotor_arg_value_valid(positions):
return False
self.set_rotor_positions(positions)
elif arg == 'rtr':
settings = value.split(" ")
if not self.is_rotor_arg_value_valid(settings):
return False
self.set_ring_settings(settings)
elif arg == 'pl':
mappings = value.split(" ")
if not self.is_plug_lead_mappings_valid(mappings):
return False
self.set_plug_lead_mappings(mappings)
elif arg == '-h':
self.print_help()
return False
else:
self.print_help()
return False
return True
def set_rotors_classes(self, rotor_labels):
rotor_classes = [rotor_cls_from_name(label) for label in rotor_labels]
self.rotor_classes = rotor_classes
def set_rotors(self):
self.rotors = [
r_cls(initial_position=self.rotor_positions[i],
ring_setting=self.ring_settings[i])
for i, r_cls in enumerate(self.rotor_classes)
]
def set_reflector_cls(self, label):
self.reflector = rotor_cls_from_name(label)
def set_reflector(self):
self.reflector = self.reflector_cls()
def set_rotor_positions(self, positions):
self.rotor_positions = positions
def set_ring_settings(self, settings):
self.ring_settings = settings
def set_plug_lead_mappings(self, mappings):
self.plug_lead_mappings = mappings
def run(self):
(_, *args) = sys.argv
if len(args) == 0 or len(args) == 1 and args[0] == '-h':
self.print_help()
return
can_proceed = self.parse_args(args)
if can_proceed:
self.create_machine()
self.accept_texts()
if __name__ == "__main__":
cli_client = EnigmaCliMachine()
cli_client.run()