File: connections.py

package info (click to toggle)
python-mcstasscript 0.0.46%2Bgit20250402111921.bfa5a26-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 11,440 kB
  • sloc: python: 13,421; makefile: 14
file content (131 lines) | stat: -rw-r--r-- 4,126 bytes parent folder | download
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
class IndexConnection:
    def __init__(self, start_index, end_index):
        self.start_index = start_index
        self.end_index = end_index

        if start_index <= end_index:
            self.interval_start = start_index
            self.interval_end = end_index
        else:
            self.interval_start = end_index
            self.interval_end = start_index

    def compatible_with(self, new):
        """
        Check if the new interval can coexist with the existing
        """
        if new.interval_end > self.interval_start and new.interval_start < self.interval_end:
            return False

        return True


class Lane:
    def __init__(self):
        self.connections = []

    def add_connection(self, start_index, end_index):
        """
        If possible adds connection and returns True, otherwise returns False
        """
        new_connection = IndexConnection(start_index, end_index)

        # A line can skip on either start or end, not both
        skipped_end = False
        skipped_start = False

        # Check if there is room for this lane
        for connection in self.connections:
            # Check for number of reasons for connection being allowed
            if connection.start_index == new_connection.start_index and not skipped_end:
                # Allow connections to collide when the start index matches
                skipped_start = True
                continue

            if connection.end_index == new_connection.end_index and not skipped_start:
                # Allow connections to collide when the end index matches
                skipped_end = True
                continue

            if connection.compatible_with(new_connection):
                # Allow if there are no index overlap in lane
                continue

            # If connection incompatible, return false
            return False

        # No problems, this connection can be included in this lane
        self.connections.append(new_connection)
        return True


class Connection:
    def __init__(self, origin, target, info=None):
        """
        Describes a connection between origin and target with lane number

        Can contain info as well which can be used for example to mark
        if the connection is part of a certain group.
        """
        self.origin = origin
        self.target = target
        self.lane_number = None
        self.info = info

    def set_lane_number(self, value):
        self.lane_number = value


class ConnectionList:
    def __init__(self):
        """
        List of connections with utility functions

        Can distribute the connections over a number of lanes to ensure all
        connections can be seen without crossing that provide ambitious
        interpretations.
        """
        self.connections = []

    def add(self, origin, target, info=None):
        self.connections.append(Connection(origin, target, info=info))

    def get_connections(self):
        return self.connections

    def get_origins(self):
        return [x.origin for x in self.connections]

    def get_targets(self):
        return [x.target for x in self.connections]

    def get_pairs(self):
        return zip(self.get_origins(), self.get_targets())

    def get_targets_for_origin(self, given_origin):

        return_targets = []
        for origin, target in self.get_pairs():
            if origin == given_origin:
                return_targets.append(target)

        return return_targets

    def distribute_lane_numbers(self, box_names):
        lanes = []

        for connection in self.connections:
            start_index = box_names.index(connection.origin.name)
            end_index = box_names.index(connection.target.name)

            proposed_lane = 0
            while True:
                if proposed_lane >= len(lanes):
                    lanes.append(Lane())

                if lanes[proposed_lane].add_connection(start_index=start_index, end_index=end_index):
                    connection.set_lane_number(proposed_lane + 1)
                    break

                proposed_lane += 1