Exemplo n.º 1
0
    def __init__(self,
                 left_rotor,
                 middle_rotor,
                 right_rotor,
                 reflector,
                 menu_link='ZZZ',
                 conx_in={},
                 conx_out={}):
        """rotors must be strings referring to either ['I','II','III','IV','V']
        reflector must be string, one of either ['B','C']"""

        self.right_rotor = right_rotor
        self.middle_rotor = middle_rotor
        self.left_rotor = left_rotor
        self.reflector = reflectors[reflector]
        self.menu_link = menu_link
        self.middle_notch = entry.index(
            notches[self.middle_rotor]
        )  ## point if right rotor reaches will trigger middle rotor to step
        self.left_notch = entry.index(
            notches[self.left_rotor]
        )  ## point if middle rotor reaches will trigger left rotor to step
        self.current_position = menu_link
        self.pos_left_rotor, self.pos_mid_rotor, self.pos_rgt_rotor = (
            ascii_uppercase.index(m) for m in menu_link.upper())
        self.status = {}
        self.status['in'] = {char: 0 for char in entry}
        self.status['out'] = {char: 0 for char in entry}
        self.conxns = {'in': conx_in, 'out': conx_out}
Exemplo n.º 2
0
    def __init__(self,
                 left_rotor: str,
                 middle_rotor: str,
                 right_rotor: str,
                 reflector: str,
                 menu_link: str = 'ZZZ'):
        """rotors must be strings referring to either ['I','II','III','IV','V']
        reflector must be string, one of either ['B','C']"""
        assert all([
            r in raw_rotors.keys()
            for r in (left_rotor, middle_rotor, right_rotor)
        ])
        assert reflector in reflectors.keys()

        self.right_rotor = right_rotor
        self.middle_rotor = middle_rotor
        self.left_rotor = left_rotor
        self.reflector = reflectors[reflector]
        self.menu_link = menu_link
        self.middle_notch = entry.index(
            notches[self.middle_rotor]
        )  ## point if right rotor reaches will trigger middle rotor to step
        self.left_notch = entry.index(
            notches[self.left_rotor]
        )  ## point if middle rotor reaches will trigger left rotor to step
        self.pos_left_rotor, self.pos_mid_rotor, self.pos_rgt_rotor = (
            ascii_uppercase.index(m) for m in menu_link.upper())
        self.in_status = {char: 0 for char in entry}
        self.out_status = {char: 0 for char in entry}
        self.current_position = menu_link
        self.record = {}
Exemplo n.º 3
0
    def once_thru_scramble(self, start_character, direction, first_rotor, pos1,
                           second_rotor, pos2, third_rotor, pos3):
        """ start_character must be single ASCII character A-Z
        direction is either 'forward' or 'back' """
        if direction == 'forward':
            usedict = {k: v for k, v in forward_rotors.items()}
        elif direction == 'back':
            usedict = {k: v for k, v in rev_rotors.items()}
        else:
            print("direction can only be 'forward' or 'back'")
            return 'wtf'

        start_character = start_character.upper()
        entry_pos = entry.index(start_character)
        fst_pos_modifier = (26 + pos1 - 0) % 26
        fst_in = (entry_pos + fst_pos_modifier) % 26
        fst_out = usedict[first_rotor][fst_in]
        ch1o = entry[fst_out]

        scd_pos_modifier = (26 + pos2 - pos1) % 26
        scd_in = (fst_out + scd_pos_modifier) % 26
        ch2i = entry[scd_in]
        scd_out = usedict[second_rotor][scd_in]
        ch2o = entry[scd_out]

        thd_pos_modifier = (26 + pos3 - pos2) % 26
        thd_in = (scd_out + thd_pos_modifier) % 26
        ch3i = entry[thd_in]
        thd_out = usedict[third_rotor][thd_in]
        ch3o = entry[thd_out]
        return ch3o
Exemplo n.º 4
0
    def full_scramble(self, in_ch):
        in_ch = in_ch.upper()
        left_rotor = self.left_rotor
        middle_rotor = self.middle_rotor
        right_rotor = self.right_rotor
        rflector = self.reflector
        # # first run right to left through scrambler
        forward_run = self.once_thru_scramble(in_ch,
                                              direction='forward',
                                              first_rotor=right_rotor,
                                              pos1=self.pos_rgt_rotor,
                                              second_rotor=middle_rotor,
                                              pos2=self.pos_mid_rotor,
                                              third_rotor=left_rotor,
                                              pos3=self.pos_left_rotor)

        # # reflector back around for return
        rfi_pos_mod = (
            26 + 0 - self.pos_left_rotor
        ) % 26  ## the '0' is there to matching formatting of other position modifiers - reflector is not moved so it will always be 0
        rf_in = (entry.index(forward_run) + rfi_pos_mod) % 26
        chri = entry[rf_in]
        mirrored = rflector[chri]

        #         print(f"{forward_run} -> {chri} (into reflector) -> {mirrored} (reflected out)")

        # # second run back left to right thru scrambler
        back_run = self.once_thru_scramble(mirrored,
                                           direction='back',
                                           first_rotor=left_rotor,
                                           pos1=self.pos_left_rotor,
                                           second_rotor=middle_rotor,
                                           pos2=self.pos_mid_rotor,
                                           third_rotor=right_rotor,
                                           pos3=self.pos_rgt_rotor)

        bk_out = entry.index(back_run)
        bko_pos_mod = (
            26 + 0 - self.pos_rgt_rotor
        ) % 26  ## as above, '0' just reflects that the entry interface doesn't move
        bk_final = (bk_out + bko_pos_mod) % 26
        final = entry[bk_final]
        #         print('RR back out:  ', back_run, '-->', final)
        #         print(in_ch,"-->",final)
        return final
Exemplo n.º 5
0
    def once_thru_scramble(self, start_character, direction, first_rotor, pos1,
                           second_rotor, pos2, third_rotor, pos3):
        """ start_character must be single ASCII character A-Z
        direction is either 'forward' or 'back' """
        if direction == 'forward':
            usedict = {k: v for k, v in forward_rotors.items()}
        elif direction == 'back':
            usedict = {k: v for k, v in rev_rotors.items()}
        else:
            print('only forward or back for direction')
            return 'wtf'
        # problem is confusion around left/middle/right rotors vs first/second/third rotors and forward/back
        # this currently works as if first = left, middle=second, third = right. If in 'forward'. Is this desired?
        start_character = start_character.upper()
        entry_pos = entry.index(start_character)
        fst_pos_modifier = (26 + pos1 - 0) % 26
        fst_in = (entry_pos + fst_pos_modifier) % 26
        fst_out = usedict[first_rotor][fst_in]
        ch1o = entry[fst_out]

        scd_pos_modifier = (26 + pos2 - pos1) % 26
        scd_in = (fst_out + scd_pos_modifier) % 26
        ch2i = entry[scd_in]
        scd_out = usedict[second_rotor][scd_in]
        ch2o = entry[scd_out]

        thd_pos_modifier = (26 + pos3 - pos2) % 26
        thd_in = (scd_out + thd_pos_modifier) % 26
        ch3i = entry[thd_in]
        thd_out = usedict[third_rotor][thd_in]
        ch3o = entry[thd_out]
        if direction == 'forward':
            print(
                f"{start_character} -> (RR out) {ch1o} -> (MR in) {ch2i} -> (MR out) {ch2o} -> (LR in) {ch3i} -> (LR out) {ch3o}"
            )
        elif direction == 'back':
            print(
                f"{start_character} -> (LR out) {ch1o} -> (MR in) {ch2i} -> (MR out) {ch2o} -> (RR in) {ch3i} -> (RR out) {ch3o}"
            )

        return ch3o
Exemplo n.º 6
0
    def nx_setup(self,
                 scale=1,
                 figsize=(15, 10),
                 width_of_scrambler=0.1,
                 height_of_scrambler=0.06):
        """For creating NetworkX graphs. Setting up base graph (BG), detailed graph (TG), figure and axes for displaying scrambler connections
        Will also effectively reset the nx Graphs"""
        self.BG = nx.Graph()
        scramblers_in_menu = [
            k if type(k) == int else 'REG' for k in menu.keys()
        ]
        self.BG.add_nodes_from(scramblers_in_menu)

        base_edges = set()
        for scr_id, descriptor_dict in self.menu.items():
            if scr_id == 'config':
                scr_id = 'REG'
            for inorout in ['in', 'out']:
                for connected_scrambler, ior in descriptor_dict['conxns'][
                        inorout].items():
                    ## the dictionary of connections that is the value for each 'conx_in/out' keys
                    base_edges.add(frozenset([
                        scr_id, connected_scrambler
                    ]))  # set of sets so not to double up

        base_edges = [tuple(be) for be in base_edges
                      ]  # turn set of frozensets into list of tuples
        self.BG.add_edges_from(base_edges)
        #         self.base_pos_for_nx = nx.circular_layout(self.BG,scale=scale)
        self.base_pos_for_nx = nx.spring_layout(self.BG, scale=scale)
        self.base_pos_for_nx['REG'] = np.array([0, -0.9])

        ## This section for the detailed graph (TG)
        self.TG = nx.Graph()
        ## this for-loop adds all nodes to the graph
        for scr_id in scramblers_in_menu:  ## for each scrambler in the menu
            for ch in entry:  ## for each letter A-Z
                for i in [
                        'I', 'O'
                ]:  ## for each end (in/out) of the double-ended scrambler
                    if scr_id == 'REG':  ## i = X (not I or O) if it's the register
                        i = 'X'
                    this_node_label = f"{scr_id}-{i}-{ch}"
                    self.TG.add_node(
                        this_node_label)  ## add a node to the graph
                    self.TG.nodes[this_node_label]["color"] = grey

        ## this for-loop adds edges for scrambler connections to the graph
        self.inter_scr_edges = set()
        for scr_id, descriptor_dict in self.menu.items(
        ):  # for each scrambler (scr_id) and its spec dict
            for inorout in ['in',
                            'out']:  # go thru the conx_in and conx_out dicts
                if scr_id == 'config':  # this just for dealing with the register
                    first_node = 'REG-X-'
                else:
                    first_node = f"{scr_id}-{iomap[inorout]}-"  # label the start of the 1st node, with either I/O
                for connected_scrambler, ior in descriptor_dict['conxns'][
                        inorout].items():  # go thru the in/out connections
                    second_node = f"{connected_scrambler}-{iomap[ior]}-"  # label the start of the 2nd node
                    for ch in entry:  # for each letter A-Z
                        self.inter_scr_edges.add(
                            frozenset([first_node + ch, second_node + ch])
                        )  # create 26 nodes with each of 1st/2nd node plus letter

        ## bit of data reformatting for the edges
        self.inter_scr_edges = [list(fs) for fs in self.inter_scr_edges]
        for edge in self.inter_scr_edges:
            edge.append({'color': grey})
        self.inter_scr_edges = [tuple(fs) for fs in self.inter_scr_edges]
        self.TG.add_edges_from(self.inter_scr_edges)

        wrange_of_letters = list(
            np.linspace(-0.5 * width_of_scrambler, 0.5 * width_of_scrambler,
                        26))

        self.manual_pos = {}

        for node in self.TG.nodes():
            scr_id, io, ch = node.split('-')
            try:
                scr_id = int(scr_id)
            except:
                pass
            x, y = self.base_pos_for_nx[scr_id]

            if io == 'I':  ## spacing apart the in from the out nodes
                y += -0.5 * height_of_scrambler  ## 'in' (I) is below
            else:
                y += 0.5 * height_of_scrambler  ## 'out' (O) is above

            x += wrange_of_letters[entry.index(ch)]
            self.manual_pos[node] = np.array([x, y])

        self.colors = [self.TG[u][v]['color'] for u, v in self.TG.edges()]

        fig, ax = plt.subplots(figsize=figsize)
        nx.draw_networkx_nodes(self.BG, pos=self.base_pos_for_nx)
        nx.draw_networkx_labels(self.BG, pos=self.base_pos_for_nx)
        nx.draw_networkx_edges(self.TG,
                               pos=self.manual_pos,
                               edge_color=self.colors)