185c0f2fbd719dab0fe8f595984d0bb9eaf82252
[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 network_generation.model.python.cube import Cube
18 from network_generation.model.python.hexagon import Hex
19 import network_generation.model.python.hexagon as Hexagon
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 * self.oRanCuSpiralRadiusOfODus * self.oRanDuSpiralRadiusOfTowers
151             + self.oRanDuSpiralRadiusOfTowers
152             + 1
153         )
154         r: int = self.oRanDuSpiralRadiusOfTowers - self.oRanCuSpiralRadiusOfODus
155         s: int = -q - r
156         return [
157             Hex(+q, +r, +s),
158             Hex(-s, -q, -r),
159             Hex(+r, +s, +q),
160             Hex(-q, -r, -s),
161             Hex(+s, +q, +r),
162             Hex(-r, -s, -q),
163         ]
164
165     def oRanCuNeighbor(self, cube: Hex, direction: int) -> list[Hex]:
166         return Hexagon.hex_add(cube, self.oRanCuDirections()[direction])
167
168     def oRanCuRing(self, center: Hex, radius: int):
169         if not (radius > 0):
170             raise ValueError(
171                 "Invalid radius. The radius around the hex center must be greater than 0 rings."
172             )
173
174         results: list[Hex] = []
175         hex: Hex = Hexagon.hex_add(
176             center, Hexagon.hex_scale(self.oRanCuDirections()[4], radius)
177         )
178         for i in range(6):
179             for j in range(radius):
180                 results.append(hex)
181                 hex = self.oRanCuNeighbor(hex, i)
182         return results
183
184     def oRanCuSpiral(self, center: Hex, radius: int) -> list[Hex]:
185         result: list[Hex] = [center]
186         for k in range(1, radius + 1):
187             result += self.oRanCuRing(center, k)
188         return result
189
190     def oRanNearRtRicDirections(self) -> list[Hex]:
191         q0: int = (
192             2 * self.oRanCuSpiralRadiusOfODus
193             + 3 * self.oRanCuSpiralRadiusOfODus * self.oRanDuSpiralRadiusOfTowers
194             + self.oRanDuSpiralRadiusOfTowers
195             + 1
196         )
197         r0: int = self.oRanDuSpiralRadiusOfTowers - self.oRanCuSpiralRadiusOfODus
198
199         q: int = 3 * q0 - self.oRanNearRtRicSpiralRadiusOfOCus
200         r: int = -r0 - self.oRanNearRtRicSpiralRadiusOfOCus
201
202         profile_id: str = self.id[0 : len(self.id)-1]
203         if profile_id in {"111", "112", "113", "114"}:
204             q: int = 21 + 14 * (self.oRanNearRtRicSpiralRadiusOfOCus - 1)
205             r: int = -7 * self.oRanNearRtRicSpiralRadiusOfOCus
206         elif profile_id in {"121", "122", "123", "124"}:
207             q: int = 25 + 13 * (self.oRanNearRtRicSpiralRadiusOfOCus - 1)
208             r: int = 9 + 10 * (self.oRanNearRtRicSpiralRadiusOfOCus - 1)
209         elif profile_id in {"131", "132"}:
210             q: int = 49 + 30 * (self.oRanNearRtRicSpiralRadiusOfOCus - 1)
211             r: int = -21 - 34 * (self.oRanNearRtRicSpiralRadiusOfOCus - 1)
212         elif profile_id == "133":
213             q: int = 74
214             r: int = 37
215         elif profile_id == "134":
216             q: int = 93
217             r: int = 50
218         elif profile_id in {"211", "212", "213", "214"}:
219             q: int = 34 + 23 * (self.oRanNearRtRicSpiralRadiusOfOCus - 1)
220             r: int = -10 * self.oRanNearRtRicSpiralRadiusOfOCus - 1
221         elif profile_id in {"221", "222", "223", "224"}:
222             q: int = 57 + 38 * (self.oRanNearRtRicSpiralRadiusOfOCus - 1)
223             r: int = -19 * self.oRanNearRtRicSpiralRadiusOfOCus
224         elif profile_id in {"231", "232", "233", "234"}:
225             q: int = 80 + 53 * (self.oRanNearRtRicSpiralRadiusOfOCus - 1)
226             r: int = -28 * self.oRanNearRtRicSpiralRadiusOfOCus - 1
227         elif profile_id in {"241", "242", "243", "244"}:
228             q: int = 103 + 68 * (self.oRanNearRtRicSpiralRadiusOfOCus - 1)
229             r: int = -39 * self.oRanNearRtRicSpiralRadiusOfOCus + 2 * (
230                 self.oRanNearRtRicSpiralRadiusOfOCus - 1
231             )
232         elif profile_id in {"311", "312", "313", "314"}:
233             q: int = 47 + 32 * (self.oRanNearRtRicSpiralRadiusOfOCus - 1)
234             r: int = -11 - 13 * (self.oRanNearRtRicSpiralRadiusOfOCus - 1)
235         elif profile_id in {"321", "322", "323", "324"}:
236             q: int = 79 + 53 * (self.oRanNearRtRicSpiralRadiusOfOCus - 1)
237             r: int = -24 - 25 * (self.oRanNearRtRicSpiralRadiusOfOCus - 1)
238         elif profile_id in {"331", "332", "333", "334"}:
239             q: int = 111 + 75 * (self.oRanNearRtRicSpiralRadiusOfOCus - 1)
240             r: int = -37 - 37 * (self.oRanNearRtRicSpiralRadiusOfOCus - 1)
241         else:
242             # Handle the default case or raise a warning
243             pass
244
245         s: int = -q - r
246         return [
247             Hex(q, r, s),
248             Hex(-s, -q, -r),
249             Hex(r, s, q),
250             Hex(-q, -r, -s),
251             Hex(s, q, r),
252             Hex(-r, -s, -q),
253         ]
254
255     def oRanNearRtRicNeighbor(self, cube: Hex, direction: int):
256         return Hexagon.hex_add(cube, self.oRanNearRtRicDirections()[direction])
257
258     def oRanNearRtRicRing(self, center: Hex, radius: int) -> list[Hex]:
259         if not (radius > 0):
260             raise ValueError(
261                 "Invalid radius. The radius around the hex center must be greater than 0 rings."
262             )
263
264         results: list[Hex] = []
265         hex: Hex = Hexagon.hex_add(
266             center, Hexagon.hex_scale(self.oRanNearRtRicDirections()[4], radius)
267         )
268         for i in range(6):
269             for j in range(radius):
270                 results.append(hex)
271                 hex = self.oRanNearRtRicNeighbor(hex, i)
272         return results
273
274     def oRanNearRtRicSpiral(self, center: Hex, radius: int) -> list[Hex]:
275         result: list[Hex] = [center]
276         for k in range(1, radius + 1):
277             result += self.oRanNearRtRicRing(center, k)
278         return result