DirectionMolecule.get_direction_for_point()   F
last analyzed

Complexity

Conditions 15

Size

Total Lines 48

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 48
rs 2.5525
cc 15

How to fix   Complexity   

Complexity

Complex classes like DirectionMolecule.get_direction_for_point() 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
from intelligine.cst import POINTS_SMELL, MOLECULES, MOLECULES_DIRECTION
2
from intelligine.core.exceptions import NoMolecule
3
from random import shuffle
4
from synergine_xyz.geometry import get_degree_from_north
5
from intelligine.synergy.event.move.direction import get_direction_for_degrees
6
7
8
class DirectionMolecule():
9
10
    WAY_UP = 'u'
11
    WAY_DOWN = 'd'
12
13
    _positions_key = None
14
15
    @classmethod
16
    def appose(cls, context, point, molecule):
17
        context.molecules().increment_with_molecule(point, molecule, context.get_cycle())
18
        context.metas.list.add(MOLECULES, MOLECULES, point, assert_not_in=False)
19
20
    @classmethod
21
    def get_direction_for_point(cls, context, point, molecule_type, molecule_way=WAY_UP):
22
        flavour = context.molecules().get_flavour(point)
23
        molecule = flavour.get_molecule(category=MOLECULES_DIRECTION, type=molecule_type)
24
25
        distance = molecule.get_distance()
26
        around_molecule_filter = lambda around_molecule: around_molecule.get_distance() <= distance #  TODO <= ?
27
        if molecule_way == cls.WAY_DOWN:
28
            around_molecule_filter = lambda around_molecule: around_molecule.get_distance() >= distance
29
        around_molecules_points = cls._get_around_molecules(context, point, molecule_type,
30
                                                            molecule_filter=around_molecule_filter)
31
32
        if not around_molecules_points \
33
           or (len(around_molecules_points) == 1 and around_molecules_points[0][0] == point):
34
            raise NoMolecule()
35
36
        shuffle(around_molecules_points)
37
        around_molecules_sorted = sorted(around_molecules_points, key=lambda x: x[1].get_intensity(), reverse=True)
38
        max_intensity = around_molecules_sorted[0][1].get_intensity()
39
40
        around_molecules_max = []
41
        for around_molecule_sorted in around_molecules_sorted:
42
            if around_molecule_sorted[1].get_intensity() == max_intensity:
43
                around_molecules_max.append(around_molecule_sorted)
44
45
        reverse = False
46
        if molecule_way == cls.WAY_DOWN:
47
            reverse = True
48
        around_molecules_sorted_by_distance = sorted(around_molecules_max,
49
                                                      key=lambda x: x[1].get_distance(),
50
                                                      reverse=reverse)
51
52
        all_same_distance = True
53
        for mol in around_molecules_sorted_by_distance:
54
            mol_mol = mol[1]
55
            if mol_mol.get_distance() != distance:
56
                all_same_distance = False
57
                break
58
59
        if all_same_distance:
60
            raise NoMolecule()
61
62
        go_to_point = around_molecules_sorted_by_distance[0][0]
63
64
        direction_degrees = get_degree_from_north(point, go_to_point)
65
        direction = get_direction_for_degrees(direction_degrees)
66
67
        return direction
68
69
    @classmethod
70
    def _get_around_molecules(cls, context, reference_point, molecule_type,
71
                              molecule_filter=lambda around_molecule: True):
72
        around_points = context.get_around_points_of_point(reference_point)
73
        around_molecules_points = []
74
        for around_point in around_points:
75
            flavour = context.molecules().get_flavour(around_point)
76
            try:
77
                around_molecule = flavour.get_molecule(category=MOLECULES_DIRECTION, type=molecule_type)
78
                if molecule_filter(around_molecule):
79
                    around_molecules_points.append((around_point, around_molecule))
80
            except NoMolecule:
81
                pass  # No molecule, ok continue to sniff around
82
83
        return around_molecules_points
84
85
    @classmethod
86
    def get_best_molecule_direction_in(cls, context, reference_point, points, molecule_type):
87
        around_molecules_points = []
88
        for around_point in points:
89
            flavour = context.molecules().get_flavour(around_point)
90
            try:
91
                around_molecule = flavour.get_molecule(category=MOLECULES_DIRECTION, type=molecule_type)
92
                around_molecules_points.append((around_point, around_molecule))
93
            except NoMolecule:
94
                pass  # Ok, no molecule, continue to sniff around
95
96
        if not around_molecules_points \
97
           or (len(around_molecules_points) == 1 and around_molecules_points[0][0] == reference_point):
98
            raise NoMolecule()
99
100
        shuffle(around_molecules_points)
101
        around_molecules_sorted = sorted(around_molecules_points, key=lambda x: x[1].get_intensity(), reverse=True)
102
        go_to_point = around_molecules_sorted[0][0]
103
104
        direction_degrees = get_degree_from_north(reference_point, go_to_point)
105
        direction = get_direction_for_degrees(direction_degrees)
106
107
        return direction