Reformat files according to template
[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 import network_generation.model.python.hexagon as Hexagon
18 from network_generation.model.python.cube import Cube
19 from network_generation.model.python.hexagon import Hex
20
21
22 class SpiralRadiusProfile:
23     def __init__(self, data: [dict[str, dict] | None] = None):
24         self._oRanSmoSpiralRadiusOfNearRtRics = (
25             data.get("oRanSmoSpiralRadiusOfNearRtRics", 1) if data else 1
26         )
27         self._oRanNearRtRicSpiralRadiusOfOCus = (
28             data.get("oRanNearRtRicSpiralRadiusOfOCus", 1) if data else 1
29         )
30         self._oRanCuSpiralRadiusOfODus = (
31             data.get("oRanCuSpiralRadiusOfODus", 1) if data else 1
32         )
33         self._oRanDuSpiralRadiusOfTowers = (
34             data.get("oRanDuSpiralRadiusOfTowers", 1) if data else 1
35         )
36
37     @property
38     def id(self) -> str:
39         return f"{self._oRanDuSpiralRadiusOfTowers}{self._oRanCuSpiralRadiusOfODus}{self._oRanNearRtRicSpiralRadiusOfOCus}{self._oRanSmoSpiralRadiusOfNearRtRics}"
40
41     @property
42     def count(self) -> int:
43         towers = 1
44         dus = 1
45         cus = 1
46         rics = 1
47
48         for ru in range(self._oRanDuSpiralRadiusOfTowers + 1):
49             towers = towers + 6 * ru
50
51         for du in range(self._oRanCuSpiralRadiusOfODus + 1):
52             dus = dus + 6 * du
53
54         for cu in range(self._oRanNearRtRicSpiralRadiusOfOCus + 1):
55             cus = cus + 6 * cu
56
57         for ric in range(self._oRanSmoSpiralRadiusOfNearRtRics + 1):
58             rics = rics + 6 * ric
59
60         return towers * dus * cus * rics
61
62     @property
63     def oRanSmoSpiralRadiusOfNearRtRics(self) -> int:
64         return self._oRanSmoSpiralRadiusOfNearRtRics
65
66     @oRanSmoSpiralRadiusOfNearRtRics.setter
67     def oRanSmoSpiralRadiusOfNearRtRics(self, value: int):
68         self._oRanSmoSpiralRadiusOfNearRtRics = value
69
70     @property
71     def oRanNearRtRicSpiralRadiusOfOCus(self) -> int:
72         return self._oRanNearRtRicSpiralRadiusOfOCus
73
74     @oRanNearRtRicSpiralRadiusOfOCus.setter
75     def oRanNearRtRicSpiralRadiusOfOCus(self, value: int):
76         self._oRanNearRtRicSpiralRadiusOfOCus = value
77
78     @property
79     def oRanCuSpiralRadiusOfODus(self) -> int:
80         return self._oRanCuSpiralRadiusOfODus
81
82     @oRanCuSpiralRadiusOfODus.setter
83     def oRanCuSpiralRadiusOfODus(self, value: int):
84         self._oRanCuSpiralRadiusOfODus = value
85
86     @property
87     def oRanDuSpiralRadiusOfTowers(self) -> int:
88         return self._oRanDuSpiralRadiusOfTowers
89
90     @oRanDuSpiralRadiusOfTowers.setter
91     def oRanDuSpiralRadiusOfTowers(self, value: int):
92         self._oRanDuSpiralRadiusOfTowers = value
93
94     @property
95     def sectors(self) -> int:
96         return self._sectors
97
98     @sectors.setter
99     def sectors(self, value: int):
100         self._sectors = value
101
102     @property
103     def nrDuCellsPerSector(self) -> int:
104         return self._nrDuCellsPerSector
105
106     @nrDuCellsPerSector.setter
107     def nrDuCellsPerSector(self, value: int):
108         self._nrDuCellsPerSector: int = value
109
110     def oRanDuDirections(self) -> list[Hex]:
111         q: int = 2 * self._oRanDuSpiralRadiusOfTowers + 1
112         r: int = -self._oRanDuSpiralRadiusOfTowers - 1
113         s: int = -q - r
114         return [
115             Hex(q, r, s),
116             Hex(-s, -q, -r),
117             Hex(r, s, q),
118             Hex(-q, -r, -s),
119             Hex(s, q, r),
120             Hex(-r, -s, -q),
121         ]
122
123     def oRanDuNeighbor(self, cube: Cube, direction: int):
124         return Hexagon.hex_add(cube, self.oRanDuDirections()[direction])
125
126     def oRanDuRing(self, center: Hex, radius: int) -> list[Hex]:
127         if radius <= 0:
128             raise ValueError(
129                 "Invalid radius. The radius around the hex center must be greater than 0 rings."
130             )
131         results: list[Hex] = []
132         hex: Hex = Hexagon.hex_add(
133             center, Hexagon.hex_scale(self.oRanDuDirections()[4], radius)
134         )
135         for i in range(6):
136             for j in range(radius):
137                 results.append(hex)
138                 hex = self.oRanDuNeighbor(hex, i)
139         return results
140
141     def oRanDuSpiral(self, o_ran_du_center: Hex, radius: int) -> list[Hex]:
142         result: list[Hex] = [o_ran_du_center]
143         for k in range(1, radius + 1):
144             result.extend(self.oRanDuRing(o_ran_du_center, k))
145         return result
146
147     def oRanCuDirections(self) -> list[Hex]:
148         q: int = (
149             2 * self.oRanCuSpiralRadiusOfODus
150             + 3
151             * self.oRanCuSpiralRadiusOfODus
152             * self.oRanDuSpiralRadiusOfTowers
153             + self.oRanDuSpiralRadiusOfTowers
154             + 1
155         )
156         r: int = (
157             self.oRanDuSpiralRadiusOfTowers - self.oRanCuSpiralRadiusOfODus
158         )
159         s: int = -q - r
160         return [
161             Hex(+q, +r, +s),
162             Hex(-s, -q, -r),
163             Hex(+r, +s, +q),
164             Hex(-q, -r, -s),
165             Hex(+s, +q, +r),
166             Hex(-r, -s, -q),
167         ]
168
169     def oRanCuNeighbor(self, cube: Hex, direction: int) -> list[Hex]:
170         return Hexagon.hex_add(cube, self.oRanCuDirections()[direction])
171
172     def oRanCuRing(self, center: Hex, radius: int):
173         if not (radius > 0):
174             raise ValueError(
175                 "Invalid radius. The radius around the hex center must be greater than 0 rings."
176             )
177
178         results: list[Hex] = []
179         hex: Hex = Hexagon.hex_add(
180             center, Hexagon.hex_scale(self.oRanCuDirections()[4], radius)
181         )
182         for i in range(6):
183             for j in range(radius):
184                 results.append(hex)
185                 hex = self.oRanCuNeighbor(hex, i)
186         return results
187
188     def oRanCuSpiral(self, center: Hex, radius: int) -> list[Hex]:
189         result: list[Hex] = [center]
190         for k in range(1, radius + 1):
191             result += self.oRanCuRing(center, k)
192         return result
193
194     def oRanNearRtRicDirections(self) -> list[Hex]:
195         q0: int = (
196             2 * self.oRanCuSpiralRadiusOfODus
197             + 3
198             * self.oRanCuSpiralRadiusOfODus
199             * self.oRanDuSpiralRadiusOfTowers
200             + self.oRanDuSpiralRadiusOfTowers
201             + 1
202         )
203         r0: int = (
204             self.oRanDuSpiralRadiusOfTowers - self.oRanCuSpiralRadiusOfODus
205         )
206
207         q: int = 3 * q0 - self.oRanNearRtRicSpiralRadiusOfOCus
208         r: int = -r0 - self.oRanNearRtRicSpiralRadiusOfOCus
209
210         profile_id: str = self.id[0 : len(self.id) - 1]
211         if profile_id in {"111", "112", "113", "114"}:
212             q: int = 21 + 14 * (self.oRanNearRtRicSpiralRadiusOfOCus - 1)
213             r: int = -7 * self.oRanNearRtRicSpiralRadiusOfOCus
214         elif profile_id in {"121", "122", "123", "124"}:
215             q: int = 25 + 13 * (self.oRanNearRtRicSpiralRadiusOfOCus - 1)
216             r: int = 9 + 10 * (self.oRanNearRtRicSpiralRadiusOfOCus - 1)
217         elif profile_id in {"131", "132"}:
218             q: int = 49 + 30 * (self.oRanNearRtRicSpiralRadiusOfOCus - 1)
219             r: int = -21 - 34 * (self.oRanNearRtRicSpiralRadiusOfOCus - 1)
220         elif profile_id == "133":
221             q: int = 74
222             r: int = 37
223         elif profile_id == "134":
224             q: int = 93
225             r: int = 50
226         elif profile_id in {"211", "212", "213", "214"}:
227             q: int = 34 + 23 * (self.oRanNearRtRicSpiralRadiusOfOCus - 1)
228             r: int = -10 * self.oRanNearRtRicSpiralRadiusOfOCus - 1
229         elif profile_id in {"221", "222", "223", "224"}:
230             q: int = 57 + 38 * (self.oRanNearRtRicSpiralRadiusOfOCus - 1)
231             r: int = -19 * self.oRanNearRtRicSpiralRadiusOfOCus
232         elif profile_id in {"231", "232", "233", "234"}:
233             q: int = 80 + 53 * (self.oRanNearRtRicSpiralRadiusOfOCus - 1)
234             r: int = -28 * self.oRanNearRtRicSpiralRadiusOfOCus - 1
235         elif profile_id in {"241", "242", "243", "244"}:
236             q: int = 103 + 68 * (self.oRanNearRtRicSpiralRadiusOfOCus - 1)
237             r: int = -39 * self.oRanNearRtRicSpiralRadiusOfOCus + 2 * (
238                 self.oRanNearRtRicSpiralRadiusOfOCus - 1
239             )
240         elif profile_id in {"311", "312", "313", "314"}:
241             q: int = 47 + 32 * (self.oRanNearRtRicSpiralRadiusOfOCus - 1)
242             r: int = -11 - 13 * (self.oRanNearRtRicSpiralRadiusOfOCus - 1)
243         elif profile_id in {"321", "322", "323", "324"}:
244             q: int = 79 + 53 * (self.oRanNearRtRicSpiralRadiusOfOCus - 1)
245             r: int = -24 - 25 * (self.oRanNearRtRicSpiralRadiusOfOCus - 1)
246         elif profile_id in {"331", "332", "333", "334"}:
247             q: int = 111 + 75 * (self.oRanNearRtRicSpiralRadiusOfOCus - 1)
248             r: int = -37 - 37 * (self.oRanNearRtRicSpiralRadiusOfOCus - 1)
249         else:
250             # Handle the default case or raise a warning
251             pass
252
253         s: int = -q - r
254         return [
255             Hex(q, r, s),
256             Hex(-s, -q, -r),
257             Hex(r, s, q),
258             Hex(-q, -r, -s),
259             Hex(s, q, r),
260             Hex(-r, -s, -q),
261         ]
262
263     def oRanNearRtRicNeighbor(self, cube: Hex, direction: int):
264         return Hexagon.hex_add(cube, self.oRanNearRtRicDirections()[direction])
265
266     def oRanNearRtRicRing(self, center: Hex, radius: int) -> list[Hex]:
267         if not (radius > 0):
268             raise ValueError(
269                 "Invalid radius. The radius around the hex center must be greater than 0 rings."
270             )
271
272         results: list[Hex] = []
273         hex: Hex = Hexagon.hex_add(
274             center,
275             Hexagon.hex_scale(self.oRanNearRtRicDirections()[4], radius),
276         )
277         for i in range(6):
278             for j in range(radius):
279                 results.append(hex)
280                 hex = self.oRanNearRtRicNeighbor(hex, i)
281         return results
282
283     def oRanNearRtRicSpiral(self, center: Hex, radius: int) -> list[Hex]:
284         result: list[Hex] = [center]
285         for k in range(1, radius + 1):
286             result += self.oRanNearRtRicRing(center, k)
287         return result