Empty TerminationPoint list
[oam.git] / code / network-generator / network_generation / model / python / o_ran_spiral_radius_profile.py
1 # Copyright 2023 highstreet technologies GmbH
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 #     http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 # !/usr/bin/python
16
17 from typing import Any
18
19 import network_generation.model.python.hexagon as Hexagon
20 from network_generation.model.python.hexagon import Hex
21
22
23 class SpiralRadiusProfile:
24     def __init__(self, data: dict[str, Any] | None = None) -> None:
25         self._oRanSmoSpiralRadiusOfNearRtRics = (
26             data.get("oRanSmoSpiralRadiusOfNearRtRics", 1) if data else 1
27         )
28         self._oRanNearRtRicSpiralRadiusOfOCus = (
29             data.get("oRanNearRtRicSpiralRadiusOfOCus", 1) if data else 1
30         )
31         self._oRanCuSpiralRadiusOfODus = (
32             data.get("oRanCuSpiralRadiusOfODus", 1) if data else 1
33         )
34         self._oRanDuSpiralRadiusOfTowers = (
35             data.get("oRanDuSpiralRadiusOfTowers", 1) if data else 1
36         )
37         # self._nrDuCellsPerSector: int = (
38         #     int(str(data.get("sectorCount"))) if data else 1
39         # )
40
41     @property
42     def id(self) -> str:
43         return "".join(
44             [
45                 str(self._oRanDuSpiralRadiusOfTowers),
46                 str(self._oRanCuSpiralRadiusOfODus),
47                 str(self._oRanNearRtRicSpiralRadiusOfOCus),
48                 str(self._oRanSmoSpiralRadiusOfNearRtRics),
49             ]
50         )
51
52     @property
53     def count(self) -> int:
54         towers = 1
55         dus = 1
56         cus = 1
57         rics = 1
58
59         for ru in range(self._oRanDuSpiralRadiusOfTowers + 1):
60             towers = towers + 6 * ru
61
62         for du in range(self._oRanCuSpiralRadiusOfODus + 1):
63             dus = dus + 6 * du
64
65         for cu in range(self._oRanNearRtRicSpiralRadiusOfOCus + 1):
66             cus = cus + 6 * cu
67
68         for ric in range(self._oRanSmoSpiralRadiusOfNearRtRics + 1):
69             rics = rics + 6 * ric
70
71         return towers * dus * cus * rics
72
73     @property
74     def oRanSmoSpiralRadiusOfNearRtRics(self) -> int:
75         return self._oRanSmoSpiralRadiusOfNearRtRics
76
77     @oRanSmoSpiralRadiusOfNearRtRics.setter
78     def oRanSmoSpiralRadiusOfNearRtRics(self, value: int) -> None:
79         self._oRanSmoSpiralRadiusOfNearRtRics = value
80
81     @property
82     def oRanNearRtRicSpiralRadiusOfOCus(self) -> int:
83         return self._oRanNearRtRicSpiralRadiusOfOCus
84
85     @oRanNearRtRicSpiralRadiusOfOCus.setter
86     def oRanNearRtRicSpiralRadiusOfOCus(self, value: int) -> None:
87         self._oRanNearRtRicSpiralRadiusOfOCus = value
88
89     @property
90     def oRanCuSpiralRadiusOfODus(self) -> int:
91         return self._oRanCuSpiralRadiusOfODus
92
93     @oRanCuSpiralRadiusOfODus.setter
94     def oRanCuSpiralRadiusOfODus(self, value: int) -> None:
95         self._oRanCuSpiralRadiusOfODus = value
96
97     @property
98     def oRanDuSpiralRadiusOfTowers(self) -> int:
99         return self._oRanDuSpiralRadiusOfTowers
100
101     @oRanDuSpiralRadiusOfTowers.setter
102     def oRanDuSpiralRadiusOfTowers(self, value: int) -> None:
103         self._oRanDuSpiralRadiusOfTowers = value
104
105     @property
106     def sectors(self) -> int:
107         return self._sectors
108
109     @sectors.setter
110     def sectors(self, value: int) -> None:
111         self._sectors = value
112
113     @property
114     def nrDuCellsPerSector(self) -> int:
115         return self._nrDuCellsPerSector
116
117     @nrDuCellsPerSector.setter
118     def nrDuCellsPerSector(self, value: int) -> None:
119         self._nrDuCellsPerSector = value
120
121     def oRanDuDirections(self) -> list[Hex]:
122         q: int = 2 * self._oRanDuSpiralRadiusOfTowers + 1
123         r: int = -self._oRanDuSpiralRadiusOfTowers - 1
124         s: int = -q - r
125         return [
126             Hex(q, r, s),
127             Hex(-s, -q, -r),
128             Hex(r, s, q),
129             Hex(-q, -r, -s),
130             Hex(s, q, r),
131             Hex(-r, -s, -q),
132         ]
133
134     def oRanDuNeighbor(self, cube: Hex, direction: int) -> Hex:
135         return Hexagon.hex_add(cube, self.oRanDuDirections()[direction])
136
137     def oRanDuRing(self, center: Hex, radius: int) -> list[Hex]:
138         if radius <= 0:
139             raise ValueError(
140                 "Invalid radius. The radius around the hex center "
141                 + "must be greater than 0 rings."
142             )
143         results: list[Hex] = []
144         hex: Hex = Hexagon.hex_add(
145             center, Hexagon.hex_scale(self.oRanDuDirections()[4], radius)
146         )
147         for i in range(6):
148             for j in range(radius):
149                 results.append(hex)
150                 hex = self.oRanDuNeighbor(hex, i)
151         return results
152
153     def oRanDuSpiral(self, o_ran_du_center: Hex, radius: int) -> list[Hex]:
154         result: list[Hex] = [o_ran_du_center]
155         for k in range(1, radius + 1):
156             result.extend(self.oRanDuRing(o_ran_du_center, k))
157         return result
158
159     def oRanCuDirections(self) -> list[Hex]:
160         q: int = (
161             2 * self.oRanCuSpiralRadiusOfODus
162             + 3
163             * self.oRanCuSpiralRadiusOfODus
164             * self.oRanDuSpiralRadiusOfTowers
165             + self.oRanDuSpiralRadiusOfTowers
166             + 1
167         )
168         r: int = (
169             self.oRanDuSpiralRadiusOfTowers - self.oRanCuSpiralRadiusOfODus
170         )
171         s: int = -q - r
172         return [
173             Hex(+q, +r, +s),
174             Hex(-s, -q, -r),
175             Hex(+r, +s, +q),
176             Hex(-q, -r, -s),
177             Hex(+s, +q, +r),
178             Hex(-r, -s, -q),
179         ]
180
181     def oRanCuNeighbor(self, cube: Hex, direction: int) -> Hex:
182         return Hexagon.hex_add(cube, self.oRanCuDirections()[direction])
183
184     def oRanCuRing(self, center: Hex, radius: int) -> list[Hex]:
185         if not (radius > 0):
186             raise ValueError(
187                 "Invalid radius. The radius around the hex center "
188                 + "must be greater than 0 rings."
189             )
190
191         results: list[Hex] = []
192         hex: Hex = Hexagon.hex_add(
193             center, Hexagon.hex_scale(self.oRanCuDirections()[4], radius)
194         )
195         for i in range(6):
196             for j in range(radius):
197                 results.append(hex)
198                 hex = self.oRanCuNeighbor(hex, i)
199         return results
200
201     def oRanCuSpiral(self, center: Hex, radius: int) -> list[Hex]:
202         result: list[Hex] = [center]
203         for k in range(1, radius + 1):
204             result += self.oRanCuRing(center, k)
205         return result
206
207     def oRanNearRtRicDirections(self) -> list[Hex]:
208         q0: int = (
209             2 * self.oRanCuSpiralRadiusOfODus
210             + 3
211             * self.oRanCuSpiralRadiusOfODus
212             * self.oRanDuSpiralRadiusOfTowers
213             + self.oRanDuSpiralRadiusOfTowers
214             + 1
215         )
216         r0: int = (
217             self.oRanDuSpiralRadiusOfTowers - self.oRanCuSpiralRadiusOfODus
218         )
219
220         q: int = 3 * q0 - self.oRanNearRtRicSpiralRadiusOfOCus
221         r: int = -r0 - self.oRanNearRtRicSpiralRadiusOfOCus
222
223         profile_id: str = self.id[0: len(self.id) - 1]
224         if profile_id in {"111", "112", "113", "114"}:
225             q = 21 + 14 * (self.oRanNearRtRicSpiralRadiusOfOCus - 1)
226             r = -7 * self.oRanNearRtRicSpiralRadiusOfOCus
227         elif profile_id in {"121", "122", "123", "124"}:
228             q = 25 + 13 * (self.oRanNearRtRicSpiralRadiusOfOCus - 1)
229             r = 9 + 10 * (self.oRanNearRtRicSpiralRadiusOfOCus - 1)
230         elif profile_id in {"131", "132"}:
231             q = 49 + 30 * (self.oRanNearRtRicSpiralRadiusOfOCus - 1)
232             r = -21 - 34 * (self.oRanNearRtRicSpiralRadiusOfOCus - 1)
233         elif profile_id == "133":
234             q = 74
235             r = 37
236         elif profile_id == "134":
237             q = 93
238             r = 50
239         elif profile_id in {"211", "212", "213", "214"}:
240             q = 34 + 23 * (self.oRanNearRtRicSpiralRadiusOfOCus - 1)
241             r = -10 * self.oRanNearRtRicSpiralRadiusOfOCus - 1
242         elif profile_id in {"221", "222", "223", "224"}:
243             q = 57 + 38 * (self.oRanNearRtRicSpiralRadiusOfOCus - 1)
244             r = -19 * self.oRanNearRtRicSpiralRadiusOfOCus
245         elif profile_id in {"231", "232", "233", "234"}:
246             q = 80 + 53 * (self.oRanNearRtRicSpiralRadiusOfOCus - 1)
247             r = -28 * self.oRanNearRtRicSpiralRadiusOfOCus - 1
248         elif profile_id in {"241", "242", "243", "244"}:
249             q = 103 + 68 * (self.oRanNearRtRicSpiralRadiusOfOCus - 1)
250             r = -39 * self.oRanNearRtRicSpiralRadiusOfOCus + 2 * (
251                 self.oRanNearRtRicSpiralRadiusOfOCus - 1
252             )
253         elif profile_id in {"311", "312", "313", "314"}:
254             q = 47 + 32 * (self.oRanNearRtRicSpiralRadiusOfOCus - 1)
255             r = -11 - 13 * (self.oRanNearRtRicSpiralRadiusOfOCus - 1)
256         elif profile_id in {"321", "322", "323", "324"}:
257             q = 79 + 53 * (self.oRanNearRtRicSpiralRadiusOfOCus - 1)
258             r = -24 - 25 * (self.oRanNearRtRicSpiralRadiusOfOCus - 1)
259         elif profile_id in {"331", "332", "333", "334"}:
260             q = 111 + 75 * (self.oRanNearRtRicSpiralRadiusOfOCus - 1)
261             r = -37 - 37 * (self.oRanNearRtRicSpiralRadiusOfOCus - 1)
262         else:
263             # Handle the default case or raise a warning
264             pass
265
266         s: int = -q - r
267         return [
268             Hex(q, r, s),
269             Hex(-s, -q, -r),
270             Hex(r, s, q),
271             Hex(-q, -r, -s),
272             Hex(s, q, r),
273             Hex(-r, -s, -q),
274         ]
275
276     def oRanNearRtRicNeighbor(self, cube: Hex, direction: int) -> Hex:
277         return Hexagon.hex_add(cube, self.oRanNearRtRicDirections()[direction])
278
279     def oRanNearRtRicRing(self, center: Hex, radius: int) -> list[Hex]:
280         if not (radius > 0):
281             raise ValueError(
282                 "Invalid radius. The radius around the hex center "
283                 + "must be greater than 0 rings."
284             )
285
286         results: list[Hex] = []
287         hex: Hex = Hexagon.hex_add(
288             center,
289             Hexagon.hex_scale(self.oRanNearRtRicDirections()[4], radius),
290         )
291         for i in range(6):
292             for j in range(radius):
293                 results.append(hex)
294                 hex = self.oRanNearRtRicNeighbor(hex, i)
295         return results
296
297     def oRanNearRtRicSpiral(self, center: Hex, radius: int) -> list[Hex]:
298         result: list[Hex] = [center]
299         for k in range(1, radius + 1):
300             result += self.oRanNearRtRicRing(center, k)
301         return result