ApexParadigmPlugin.__passive_digipeat()   F
last analyzed

Complexity

Conditions 25

Size

Total Lines 78

Duplication

Lines 18
Ratio 23.08 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 25
c 3
b 0
f 0
dl 18
loc 78
rs 2.3445

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Complexity

Complex classes like ApexParadigmPlugin.__passive_digipeat() often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
#!/usr/bin/env python
2
# -*- coding: utf-8 -*-
3
4
# These imports are for python3 compatibility inside python2
5
from __future__ import absolute_import
6
from __future__ import division
7
from __future__ import print_function
8
9
import copy
10
import re
11
12
import apex.routing
13
14
__author__ = 'Jeffrey Phillips Freeman (WI2ARD)'
15
__maintainer__ = 'Jeffrey Phillips Freeman (WI2ARD)'
16
__email__ = '[email protected]'
17
__license__ = 'Apache License, Version 2.0'
18
__copyright__ = 'Copyright 2016, Syncleus, Inc. and contributors'
19
__credits__ = []
20
__version__ = '0.0.6'
21
22
plugin = None
23
24
25
def start(config, port_map, aprsis):
26
    global plugin
27
    plugin = ApexParadigmPlugin(config, port_map, aprsis)
28
    plugin.run()
29
30
31
def handle_packet(frame, recv_port, recv_port_name):
32
    plugin.handle_packet(frame, recv_port, recv_port_name)
33
34
35
def stop():
36
    plugin.stop()
37
38
39
class ApexParadigmPlugin(object):
40
41
    BAND_PATH_REGEX = re.compile(r'(\d{1,4})M(\d{0,3})')
42
43
    def __init__(self, config, port_map, aprsis):
44
        self.port_map = port_map
45
        self.aprsis = aprsis
46
47
    def __passive_digipeat(self, frame, recv_port, recv_port_name):
48
        # can't digipeat packets if we are in the expended path
49
        if apex.routing.has_seen(self.port_map, frame):
50
            return
51
52
        for hop_index in range(0, len(frame['path'])):
53
            hop = frame['path'][hop_index]
54
            if not apex.routing.is_hop_consumed(hop):
55
                split_hop = hop.split('-')
56
                node = split_hop[0].upper()
57
                if len(split_hop) >= 2 and split_hop[1]:
58
                    ssid = int(split_hop[1])
59
                else:
60
                    ssid = 0
61
62
                band_path = None
63
                band_path_net = None
64
                band_match = self.BAND_PATH_REGEX.match(node)
65
                if band_match is not None:
66
                    band_path = band_match.group(1)
67
                    band_path_net = band_match.group(2)
68
69
                for port_name in self.port_map.keys():
70
                    port = self.port_map[port_name]
71
                    split_port_identifier = port['identifier'].split('-')
72
                    port_callsign = split_port_identifier[0].upper()
73
                    if len(split_port_identifier) >= 2 and split_port_identifier[1]:
74
                        port_ssid = int(split_port_identifier[1])
75
                    else:
76
                        port_ssid = 0
77
78
                    if band_path:
79
                        if band_path_net:
80
                            if node == port['net']:
81
                                frame['path'] = frame['path'][:hop_index] + [recv_port['identifier'] + '*'] +\
82 View Code Duplication
                                                [hop + '*'] + frame['path'][hop_index+1:]
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
83
                                port['tnc'].write(frame, port['tnc_port'])
84
                                self.aprsis.write(frame)
85
                                return
86
                        else:
87
                            if port['net'].startswith(node):
88
                                frame['path'] = frame['path'][:hop_index] + [recv_port['identifier'] + '*'] +\
89 View Code Duplication
                                                [hop + '*'] + frame['path'][hop_index+1:]
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
90
                                port['tnc'].write(frame, port['tnc_port'])
91
                                self.aprsis.write(frame)
92
                                return
93
                    if node == port_callsign and ssid == port_ssid:
94
                        if ssid is 0:
95
                            frame['path'][hop_index] = port_callsign + '*'
96
                        else:
97
                            frame['path'][hop_index] = port['identifier'] + '*'
98
                        port['tnc'].write(frame, port['tnc_port'])
99
                        self.aprsis.write(frame)
100
                        return
101
                    elif node == 'GATE' and port['net'].startswith('2M'):
102
                        frame['path'] = frame['path'][:hop_index] + [recv_port['identifier'] + '*'] + [node + '*'] +\
103 View Code Duplication
                                        frame['path'][hop_index+1:]
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
104
                        port['tnc'].write(frame, port['tnc_port'])
105
                        self.aprsis.write(frame)
106
                        return
107
                if node.startswith('WIDE') and ssid > 1:
108
                    frame['path'] = frame['path'][:hop_index] + [recv_port['identifier'] + '*'] +\
109
                        [node + '-' + str(ssid-1)] + frame['path'][hop_index+1:]
110
                    port['tnc'].write(frame, port['tnc_port'])
111
                    self.aprsis.write(frame)
112
                    return
113
                elif node.startswith('WIDE') and ssid is 1:
114
                    frame['path'] = frame['path'][:hop_index] + [recv_port['identifier'] + '*'] + [node + '*'] + frame['path'][hop_index+1:]
115
                    port['tnc'].write(frame, port['tnc_port'])
116
                    self.aprsis.write(frame)
117
                    return
118
                elif node.startswith('WIDE') and ssid is 0:
119
                    frame['path'][hop_index] = node + '*'
120
                    # no return
121
                else:
122
                    # If we didnt digipeat it then we didn't modify the frame, send it to aprsis as-is
123
                    self.aprsis.write(frame)
124
                    return
125
126
    def __preemptive_digipeat(self, frame, recv_port, recv_port_name):
127
        # can't digipeat packets if we are in the expended path
128
        if apex.routing.has_seen(self.port_map, frame):
129
            return
130
131
        selected_hop = {}
132
        node = None
133
        ssid = 0
134
        for hop_index in reversed(range(0, len(frame['path']))):
135
            hop = frame['path'][hop_index]
136
            # If this is the last node before a spent node, or a spent node itself, we are done
137
            if apex.routing.is_hop_consumed(hop) or apex.routing.is_hop_consumed(frame['path'][hop_index-1]):
138
                break
139
            split_hop = hop.split('-')
140
            node = split_hop[0].upper()
141
            if len(split_hop) >= 2 and split_hop[1]:
142
                ssid = int(split_hop[1])
143
            else:
144
                continue
145
146
            band_path = None
147
            band_path_net = None
148
            band_match = self.BAND_PATH_REGEX.match(node)
149
            if band_match is not None:
150
                band_path = band_match.group(1)
151
                band_path_net = band_match.group(2)
152
153
            if not band_path:
154
                continue
155
156
            for port_name in self.port_map.keys():
157
                port = self.port_map[port_name]
158
                if band_path_net and node == port['net']:
159
                    # only when a ssid is present should it be treated preemptively if it is a band path
160
                    if not selected_hop:
161
                        selected_hop['index'] = hop_index
162
                        selected_hop['hop'] = hop
163
                        selected_hop['node'] = node
164
                        selected_hop['ssid'] = ssid
165
                        selected_hop['port_name'] = port_name
166
                        selected_hop['port'] = port
167
                        selected_hop['band_path'] = band_path
168
                        selected_hop['band_path_net'] = band_path_net
169
                    elif ssid > selected_hop['ssid']:
170
                        selected_hop['index'] = hop_index
171
                        selected_hop['hop'] = hop
172
                        selected_hop['node'] = node
173
                        selected_hop['ssid'] = ssid
174
                        selected_hop['port_name'] = port_name
175
                        selected_hop['port'] = port
176
                        selected_hop['band_path'] = band_path
177
                        selected_hop['band_path_net'] = band_path_net
178
                elif not band_path_net and port['net'].startswith(band_path):
179
                    # only when a ssid is present should it be treated preemptively if it is a band path
180
                    if not selected_hop:
181
                        selected_hop['index'] = hop_index
182
                        selected_hop['hop'] = hop
183
                        selected_hop['node'] = node
184
                        selected_hop['ssid'] = ssid
185
                        selected_hop['port_name'] = port_name
186
                        selected_hop['port'] = port
187
                        selected_hop['band_path'] = band_path
188 View Code Duplication
                        selected_hop['band_path_net'] = band_path_net
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
189
                    elif ssid > selected_hop['ssid']:
190
                        selected_hop['index'] = hop_index
191
                        selected_hop['hop'] = hop
192
                        selected_hop['node'] = node
193
                        selected_hop['ssid'] = ssid
194
                        selected_hop['port_name'] = port_name
195
                        selected_hop['port'] = port
196
                        selected_hop['band_path'] = band_path
197
                        selected_hop['band_path_net'] = band_path_net
198
        for hop_index in reversed(range(0, len(frame['path']))):
199
            hop = frame['path'][hop_index]
200
            # If this is the last node before a spent node, or a spent node itself, we are done
201
            if apex.routing.is_hop_consumed(hop) or apex.routing.is_hop_consumed(frame['path'][hop_index-1]):
202
                break
203
            elif selected_hop and selected_hop['index'] <= hop_index:
204
                break
205
206 View Code Duplication
            for port_name in self.port_map.keys():
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
207
                port = self.port_map[port_name]
208
209
                # since the callsign specifically was specified in the path after the band-path the callsign takes
210
                # precedence
211
                if port['identifier'] == hop:
212
                    selected_hop['index'] = hop_index
213
                    selected_hop['hop'] = hop
214
                    selected_hop['node'] = node
215
                    selected_hop['ssid'] = ssid
216
                    selected_hop['port_name'] = port_name
217
                    selected_hop['port'] = port
218
                    selected_hop['band_path'] = None
219
                    selected_hop['band_path_net'] = None
220
221
        if not selected_hop:
222
            return
223
224
        # now lets digipeat this packet
225
        new_path = []
226
        for hop_index in range(0, len(frame['path'])):
227
            hop = frame['path'][hop_index]
228
            if not apex.routing.is_hop_consumed(hop):
229
                if hop_index == selected_hop['index']:
230
                    if selected_hop['band_path'] is None:
231
                        new_path += [hop + '*']
232
                    else:
233
                        new_path += [selected_hop['port']['identifier'] + '*'] + [hop + '*']
234
                elif hop_index > selected_hop['index']:
235
                    new_path += [hop]
236
            else:
237
                new_path += [hop]
238
        frame['path'] = new_path
239
        port['tnc'].write(frame, port['tnc_port'])
240
        self.aprsis.write(frame)
241
        return
242
243
    def stop(self):
244
        return
245
246
    def run(self):
247
        return
248
249
    def handle_packet(self, frame, recv_port, recv_port_name):
250
        self.__preemptive_digipeat(copy.deepcopy(frame), recv_port, recv_port_name)
251
        self.__passive_digipeat(copy.deepcopy(frame), recv_port, recv_port_name)
252