diff --git a/.github/workflows/python-app.yml b/.github/workflows/python-app.yml index 66d0889..34fd777 100644 --- a/.github/workflows/python-app.yml +++ b/.github/workflows/python-app.yml @@ -31,7 +31,7 @@ jobs: poetry run isort -c . - name: Lint with pylint run: | - poetry run pylint yaramo + poetry run pylint yaramo --fail-under 6 test: diff --git a/test/__init__.py b/test/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/test/topology_test.py b/test/topology_test.py new file mode 100644 index 0000000..26938da --- /dev/null +++ b/test/topology_test.py @@ -0,0 +1,25 @@ +from yaramo.model import Edge, Node, Topology + + +def test_get_edge_by_nodes(): + topology = Topology() + + node_a = Node() + node_b = Node() + node_c = Node() + topology.add_node(node_a) + topology.add_node(node_b) + topology.add_node(node_c) + assert len(topology.nodes) == 3 + + edge = Edge(node_a, node_b) + topology.add_edge(edge) + assert len(topology.edges) == 1 + + def _test_edge(_node_a, _node_b, _expected_edge): + _edge = topology.get_edge_by_nodes(_node_a, _node_b) + assert _edge == _expected_edge + + _test_edge(node_a, node_b, edge) + _test_edge(node_b, node_a, edge) + _test_edge(node_a, node_c, None) diff --git a/yaramo/__init__.py b/yaramo/__init__.py index 139597f..8b13789 100644 --- a/yaramo/__init__.py +++ b/yaramo/__init__.py @@ -1,2 +1 @@ - diff --git a/yaramo/base_element.py b/yaramo/base_element.py index b8ee0d9..9ee095c 100644 --- a/yaramo/base_element.py +++ b/yaramo/base_element.py @@ -16,7 +16,7 @@ def to_serializable(self) -> Tuple[dict, dict]: In subclasses this creates a dictionary with immediately serializable attributes and references (uuids) to attributes that are objects and also a second dictionary where said objects are serialized (by deligation). - + Serialization ------------- The idea is to collect all attributes of an object that can be serialized immediately and diff --git a/yaramo/edge.py b/yaramo/edge.py index b2ef316..f3b5c6c 100644 --- a/yaramo/edge.py +++ b/yaramo/edge.py @@ -10,12 +10,19 @@ class Edge(BaseElement): """This class is one of two Elements (Edge and Node) comprising the base of the yaramo Topology. An Edge is fundamentally defined by two Nodes (a and b). It does have a list of GeoNodes and a list of Signals - that may be on that Edge. An Edge can have a length set on construction, however if that is not the case, + that may be on that Edge. An Edge can have a length set on construction, however if that is not the case, the length can be calculated by calling update_length(). This sets the length based on the GeoNodes referred to by node_a and node_b as well as any intermediate_geo_nodes. The maximum_speed of an Edge cannot be set on construction but will generally be determined based on the connected Topology and Signals. """ - def __init__(self, node_a: Node, node_b: Node, vacancy_section: Optional[VacancySection] = None, length: float = None, **kwargs): + def __init__( + self, + node_a: Node, + node_b: Node, + vacancy_section: Optional[VacancySection] = None, + length: float = None, + **kwargs + ): """ Parameters ---------- diff --git a/yaramo/geo_node.py b/yaramo/geo_node.py index 43848ea..8ab1cf0 100644 --- a/yaramo/geo_node.py +++ b/yaramo/geo_node.py @@ -6,7 +6,7 @@ class GeoNode(ABC, BaseElement): """This is the baseclass of specific GeoNodes that use different coordinate systems. - + A GeoNode refers to a GeoPoint as a means of location. """ diff --git a/yaramo/geo_point.py b/yaramo/geo_point.py index 039a4bc..4deca5c 100644 --- a/yaramo/geo_point.py +++ b/yaramo/geo_point.py @@ -9,7 +9,7 @@ class GeoPoint(ABC, BaseElement): """This is the baseclass of specific GeoPoints that use different coordinate systems. - + A GeoPoint is characterized by it's x and y coordinates. """ diff --git a/yaramo/model.py b/yaramo/model.py index ec879fa..6e47250 100644 --- a/yaramo/model.py +++ b/yaramo/model.py @@ -1,5 +1,5 @@ from yaramo.edge import Edge # pylint: noqa -from yaramo.geo_node import GeoNode, Wgs84GeoNode, DbrefGeoNode # pylint: noqa +from yaramo.geo_node import DbrefGeoNode, GeoNode, Wgs84GeoNode # pylint: noqa from yaramo.node import Node, NodeConnectionDirection # pylint: noqa from yaramo.route import Route # pylint: noqa from yaramo.signal import Signal, SignalDirection, SignalFunction, SignalKind # pylint: noqa diff --git a/yaramo/node.py b/yaramo/node.py index 2c68f1a..f145108 100644 --- a/yaramo/node.py +++ b/yaramo/node.py @@ -19,7 +19,7 @@ class Node(BaseElement): We assume that there are only Nodes connected on all three or only one connection. There can be a GeoNode associated with a Node to add a geo-location. """ - + def __init__(self, turnout_side=None, **kwargs): """ Parameters @@ -81,8 +81,8 @@ def get_possible_followers(self, source): return [self.connected_on_head] def get_anschluss_of_other(self, other: "Node") -> NodeConnectionDirection: - """ Gets the Anschluss (Ende, Links, Rechts, Spitze) of other node. - + """Gets the Anschluss (Ende, Links, Rechts, Spitze) of other node. + Idea: We assume, the current node is a point and we want to estimate the Anschluss of the other node. """ @@ -111,8 +111,13 @@ def get_arc_between_nodes(_node_a: "Node", _node_b: "Node"): return math.degrees(math.acos((_a * _a + _b * _b - _c * _c) / (2.0 * _a * _b))) - def is_above_line_between_points(head_point: GeoPoint, branching_point: GeoPoint, comparison_point: GeoPoint): - return ((branching_point.x - head_point.x)*(comparison_point.y - head_point.y) - (branching_point.y - head_point.y)*(comparison_point.x - head_point.x)) > 0 + def is_above_line_between_points( + head_point: GeoPoint, branching_point: GeoPoint, comparison_point: GeoPoint + ): + return ( + (branching_point.x - head_point.x) * (comparison_point.y - head_point.y) + - (branching_point.y - head_point.y) * (comparison_point.x - head_point.x) + ) > 0 current_max_arc = 361 other_a: "Node" = None @@ -131,12 +136,20 @@ def is_above_line_between_points(head_point: GeoPoint, branching_point: GeoPoint current_max_arc = cur_arc # Check on which side of the line between the head connection and this node the other nodes are - side_a = is_above_line_between_points(self.connected_on_head.geo_node.geo_point, self.geo_node.geo_point, other_a.geo_node.geo_point) - side_b = is_above_line_between_points(self.connected_on_head.geo_node.geo_point, self.geo_node.geo_point, other_b.geo_node.geo_point) + side_a = is_above_line_between_points( + self.connected_on_head.geo_node.geo_point, + self.geo_node.geo_point, + other_a.geo_node.geo_point, + ) + side_b = is_above_line_between_points( + self.connected_on_head.geo_node.geo_point, + self.geo_node.geo_point, + other_b.geo_node.geo_point, + ) # If they're on two separate sides we know which is left and right - if(side_a != side_b): - if (side_a): + if side_a != side_b: + if side_a: self.connected_on_left, self.connected_on_right = other_a, other_b else: self.connected_on_right, self.connected_on_left = other_a, other_b @@ -145,11 +158,14 @@ def is_above_line_between_points(head_point: GeoPoint, branching_point: GeoPoint else: arc_a = get_arc_between_nodes(self.connected_on_head, other_a) arc_b = get_arc_between_nodes(self.connected_on_head, other_b) - if(arc_a > arc_b): - self.connected_on_right, self.connected_on_left = (other_a, other_b) if side_a else (other_b, other_a) + if arc_a > arc_b: + self.connected_on_right, self.connected_on_left = ( + (other_a, other_b) if side_a else (other_b, other_a) + ) else: - self.connected_on_left, self.connected_on_right = (other_a, other_b) if side_a else (other_b, other_a) - + self.connected_on_left, self.connected_on_right = ( + (other_a, other_b) if side_a else (other_b, other_a) + ) def to_serializable(self): """See the description in the BaseElement class. @@ -157,7 +173,7 @@ def to_serializable(self): Returns: A serializable dictionary and a dictionary with serialized objects (GeoNodes). """ - + attributes = self.__dict__ references = { "connected_on_head": self.connected_on_head.uuid if self.connected_on_head else None, diff --git a/yaramo/route.py b/yaramo/route.py index ffe3e46..b5fbb50 100644 --- a/yaramo/route.py +++ b/yaramo/route.py @@ -2,14 +2,14 @@ from yaramo.base_element import BaseElement from yaramo.edge import Edge -from yaramo.signal import Signal from yaramo.node import Node +from yaramo.signal import Signal from yaramo.vacancy_section import VacancySection class Route(BaseElement): """A Route is a collection of edges defined by a start and end signal. - + There are usally vacancy sections associated with a route. """ @@ -22,7 +22,7 @@ def __init__(self, start_signal: Signal, maximum_speed: Optional[int] = None, ** maximum_speed: int The maximum allowed speed going over the whole Route. """ - + super().__init__(**kwargs) self.maximum_speed: int = maximum_speed self.edges: set[Edge] = set([start_signal.edge]) @@ -110,14 +110,14 @@ def to_serializable(self) -> Dict: Returns: A serializable dictionary with all attributes of the Route. """ - + attributes = self.__dict__ references = { "maximum_speed": self.maximum_speed, "edges": [edge.uuid for edge in self.edges], "start_signal": self.start_signal.uuid, "end_signal": self.end_signal.uuid if self.end_signal else None, - "vacancy_sections": self.vacancy_sections + "vacancy_sections": self.vacancy_sections, } return {**attributes, **references}, {} diff --git a/yaramo/signal.py b/yaramo/signal.py index b88e610..77f06f1 100644 --- a/yaramo/signal.py +++ b/yaramo/signal.py @@ -1,5 +1,5 @@ from enum import Enum -from typing import Tuple, List, Set +from typing import List, Set, Tuple from uuid import uuid4 from yaramo.additional_signal import AdditionalSignal @@ -32,6 +32,7 @@ def __str__(self): class SignalKind(Enum): """The SignalFunction determines the type of a Signal.""" + Hauptsignal = 0 Mehrabschnittssignal = 1 Vorsignal = 2 @@ -45,6 +46,7 @@ def __str__(self): class SignalState(Enum): """The SignalState determines a possible state of a Signal.""" + hp0 = 0 hp1 = 1 hp2 = 2 diff --git a/yaramo/topology.py b/yaramo/topology.py index 67452bb..358f875 100644 --- a/yaramo/topology.py +++ b/yaramo/topology.py @@ -8,7 +8,7 @@ class Topology(BaseElement): """The Topology is a collection of all track elements comprising that topology. - + Elements like Signals, Nodes, Edges, Routes and Vacancy Sections can be accessed by their uuid in their respective dictionary. """ @@ -74,5 +74,5 @@ def to_serializable(self): "signals": signals, "routes": routes, "objects": objects, - "vacany_sections": vacancy_sections + "vacany_sections": vacancy_sections, }, {} diff --git a/yaramo/vacancy_section.py b/yaramo/vacancy_section.py index 25fcbb7..d02126e 100644 --- a/yaramo/vacancy_section.py +++ b/yaramo/vacancy_section.py @@ -1,4 +1,5 @@ from typing import Tuple + from yaramo.base_element import BaseElement