source: src/mlx/gates.py@ 1159:6229730a50ed

python3
Last change on this file since 1159:6229730a50ed was 1158:7fea55a5d04c, checked in by István Váradi <ivaradi@…>, 7 months ago

Updated the taxi-through properties of the gates based on the airport data (re #386).

File size: 11.8 KB
Line 
1#--------------------------------------------------------------------------------------
2
3## @package mlx.gates
4#
5# The module to handle the LHBP gate information.
6#
7
8#--------------------------------------------------------------------------------------
9
10class Gate(object):
11 """Information about a gate."""
12 def __init__(self, number, terminal, type,
13 availableFn = None, taxiThrough = False,
14 maxSpan = 0.0, maxLength = 0.0):
15 """Construct the gate with the given information.
16
17 number is the gate's number as a string (as it can contain letters).
18 terminal is the terminal the gate belongs to (not used currently).
19 type is the gate's type: G for gate, S for stand.
20 availableFn is a function that can determine if the gate is available based on
21 the statuses of other gates. Its arguments are:
22 - a collection of the gates, and
23 - a set of occupied gate numbers."""
24 self.number = number
25 self.terminal = terminal
26 self.type = type
27 self._availableFn = availableFn
28 self.taxiThrough = taxiThrough
29 self.maxSpan = maxSpan
30 self.maxLength = maxLength
31
32 def isAvailable(self, plane, gates, occupiedGateNumbers):
33 """Determine if this gate is available for the given plane and the
34 given the set of gates and occupied gate numbers."""
35 if self.number in occupiedGateNumbers:
36 return False
37 if self._availableFn is None or \
38 self._availableFn(gates, occupiedGateNumbers):
39 return plane is None or \
40 ((self.maxSpan<0.1 or plane.wingSpan <= self.maxSpan) and
41 (self.maxLength<0.1 or plane.fuselageLength <= self.maxLength) and
42 (not plane.hasStairs or self.type!="G"))
43 else:
44 return False
45
46#--------------------------------------------------------------------------------------
47
48class Gates(object):
49 """A collection of gates."""
50 # Display info type: a gate (number)
51 DISPLAY_GATE=1
52
53 # Display info type: a space
54 DISPLAY_SPACE=2
55
56 # Display info type: a new column
57 DISPLAY_NEW_COLUMN=3
58
59 def __init__(self):
60 """Construct the gate collection."""
61 self._gates = []
62 self._displayInfos = []
63 self._numColumns = 1
64 self._numRows = 0
65 self._numRowsInColumn = 0
66
67 @property
68 def gates(self):
69 """Get an iterator over the gates."""
70 return iter(self._gates)
71
72 @property
73 def displayInfos(self):
74 """Get an iterator over the display info tuples.
75
76 Each tuple consists of
77 - a type (one of the DISPLAY_XXX constants), and
78 - an additional data (the gate for DISPLAY_GATE, None for others)."""
79 return iter(self._displayInfos)
80
81 @property
82 def numRows(self):
83 """Get the number of rows."""
84 return self._numRows
85
86 @property
87 def numColumns(self):
88 """Get the number of columns."""
89 return self._numColumns
90
91 def add(self, gate):
92 """Add a gate to the collection."""
93 self._gates.append(gate)
94 self._displayInfos.append((Gates.DISPLAY_GATE, gate))
95 self._addRow()
96
97 def find(self, gateNumber):
98 """Find a gate by its number."""
99 for gate in self._gates:
100 if gate.number == gateNumber:
101 return gate
102
103 def addSpace(self):
104 """Add a space between subsequent gates."""
105 self._displayInfos.append((Gates.DISPLAY_SPACE, None))
106 self._addRow()
107
108 def addNewColumn(self):
109 """Start a new column of gates."""
110 self._displayInfos.append((Gates.DISPLAY_NEW_COLUMN, None))
111 self._numRowsInColumn = 0
112 self._numColumns += 1
113
114 def merge(self, otherGates):
115 """Merge the information from the given gate list (retrieved from the
116 MAVA server) into this gate list."""
117 for otherGate in otherGates.gates:
118 gate = self.find(otherGate.number)
119 if gate is None:
120 print("Received data for gate %s, but it does not exist locally!" %
121 (otherGate.number,))
122 else:
123 if gate.terminal != otherGate.terminal:
124 print("The terminal for gate %s is received as: %s" %
125 (gate.number, otherGate.terminal))
126 gate.terminal = otherGate.terminal
127 if gate.type != otherGate.type:
128 print("The type for gate %s is received as: %s" %
129 (gate.number, otherGate.type))
130 gate.type = otherGate.type
131
132 gate.maxSpan = otherGate.maxSpan
133 gate.maxLength = otherGate.maxLength
134
135 for gate in self.gates:
136 if gate.maxSpan==0.0 or gate.maxLength==0.0:
137 print("Gate %s has no maximal dimensions from the database" %
138 (gate.number,))
139
140 def _addRow(self):
141 """Add a new row."""
142 self._numRowsInColumn += 1
143 if self._numRowsInColumn > self._numRows:
144 self._numRows = self._numRowsInColumn
145
146#--------------------------------------------------------------------------------------
147
148def availableIf(occupiedGateNumbers, othersAvailable = []):
149 """Determine if a gate is available.
150
151 othersAvailable is a list of numbers of gates, that must be available so
152 that the one we are considering is available."""
153 for otherNumber in othersAvailable:
154 if otherNumber in occupiedGateNumbers:
155 return False
156 return True
157
158#--------------------------------------------------------------------------------------
159
160def getAvailableIf(othersAvailable = []):
161 """Get a function that determines if a gate is available based on the
162 statuses of other gates."""
163 return lambda gates, occupiedGateNumbers: availableIf(occupiedGateNumbers,
164 othersAvailable =
165 othersAvailable)
166
167#--------------------------------------------------------------------------------------
168
169# The gates at LHBP
170lhbpGates = Gates()
171
172lhbpGates.add(Gate("R101", "1", "S", taxiThrough = True))
173lhbpGates.add(Gate("R102", "1", "S"))
174lhbpGates.add(Gate("R103", "1", "S"))
175lhbpGates.add(Gate("R104", "1", "S",
176 availableFn = getAvailableIf(othersAvailable = ["R105"])))
177lhbpGates.add(Gate("R105", "1", "S",
178 availableFn = getAvailableIf(othersAvailable = ["R104", "R106"])))
179lhbpGates.add(Gate("R106", "1", "S",
180 availableFn = getAvailableIf(othersAvailable = ["R105", "R108"])))
181lhbpGates.add(Gate("R107", "1", "S",
182 availableFn = getAvailableIf(othersAvailable = ["R108"])))
183lhbpGates.add(Gate("R108", "1", "S",
184 availableFn = getAvailableIf(othersAvailable = ["R106", "R107"])))
185
186lhbpGates.addSpace()
187lhbpGates.add(Gate("R110", "1", "S",
188 availableFn = getAvailableIf(othersAvailable = ["R111"])))
189lhbpGates.add(Gate("R111", "1", "S",
190 availableFn = getAvailableIf(othersAvailable = ["R110", "R112"])))
191lhbpGates.add(Gate("R112", "1", "S",
192 availableFn = getAvailableIf(othersAvailable = ["R111"])))
193lhbpGates.add(Gate("R113", "1", "S",
194 availableFn = getAvailableIf(othersAvailable = ["R112", "R114"])))
195lhbpGates.add(Gate("R114", "1", "S",
196 availableFn = getAvailableIf(othersAvailable = ["R113"])))
197lhbpGates.add(Gate("R115", "1", "S"))
198lhbpGates.add(Gate("R116", "1", "S",
199 availableFn = getAvailableIf(othersAvailable = ["R117"]),
200 taxiThrough = True))
201lhbpGates.add(Gate("R117", "1", "S",
202 availableFn = getAvailableIf(othersAvailable = ["R116", "R117A"])))
203lhbpGates.add(Gate("R117A", "1", "S",
204 availableFn = getAvailableIf(othersAvailable = ["R116", "R117"])))
205lhbpGates.addNewColumn()
206
207lhbpGates.add(Gate("G150", "1", "S"))
208lhbpGates.add(Gate("G151", "1", "S"))
209lhbpGates.add(Gate("G152", "1", "S"))
210lhbpGates.add(Gate("G153", "1", "S"))
211lhbpGates.add(Gate("G154", "1", "S"))
212lhbpGates.add(Gate("G155", "1", "S"))
213
214lhbpGates.addSpace()
215lhbpGates.add(Gate("G170", "1", "S", taxiThrough = True))
216lhbpGates.add(Gate("G171", "1", "S", taxiThrough = True))
217lhbpGates.add(Gate("G172", "1", "S", taxiThrough = True))
218lhbpGates.addNewColumn()
219
220lhbpGates.add(Gate("31", "2B", "G"))
221lhbpGates.add(Gate("32", "2B", "G"))
222lhbpGates.add(Gate("33", "2B", "G"))
223lhbpGates.add(Gate("34", "2B", "G",
224 availableFn = getAvailableIf(othersAvailable = ["34L", "34R"])))
225lhbpGates.add(Gate("34L", "2B", "G",
226 availableFn = getAvailableIf(othersAvailable = ["34", "34R"])))
227lhbpGates.add(Gate("34R", "2B", "G",
228 availableFn = getAvailableIf(othersAvailable = ["34L", "34"])))
229lhbpGates.add(Gate("35", "2B", "G",
230 availableFn = getAvailableIf(othersAvailable = ["35L", "35R"])))
231lhbpGates.add(Gate("35L", "2B", "G",
232 availableFn = getAvailableIf(othersAvailable = ["35", "35R"])))
233lhbpGates.add(Gate("35R", "2B", "G",
234 availableFn = getAvailableIf(othersAvailable = ["35L", "35"])))
235lhbpGates.add(Gate("36", "2B", "G",
236 availableFn = getAvailableIf(othersAvailable = ["36L", "36R"])))
237lhbpGates.add(Gate("36L", "2B", "G",
238 availableFn = getAvailableIf(othersAvailable = ["36", "36R"])))
239lhbpGates.add(Gate("36R", "2B", "G",
240 availableFn = getAvailableIf(othersAvailable = ["36L", "36"])))
241lhbpGates.addSpace()
242
243lhbpGates.add(Gate("37", "2B", "G"))
244lhbpGates.add(Gate("38", "2B", "G"))
245lhbpGates.add(Gate("39", "2B", "G",
246 availableFn = getAvailableIf(othersAvailable = ["37L", "37R"])))
247lhbpGates.add(Gate("39L", "2B", "G",
248 availableFn = getAvailableIf(othersAvailable = ["37", "37R"])))
249lhbpGates.add(Gate("39R", "2B", "G",
250 availableFn = getAvailableIf(othersAvailable = ["37L", "37"])))
251lhbpGates.addNewColumn()
252
253lhbpGates.add(Gate("42", "2A", "G"))
254lhbpGates.add(Gate("43", "2A", "G"))
255lhbpGates.add(Gate("44", "2A", "G"))
256lhbpGates.add(Gate("45", "2A", "G"))
257lhbpGates.addSpace()
258
259lhbpGates.add(Gate("R210", "2A", "S",
260 availableFn = getAvailableIf(othersAvailable = ["R212A"]),
261 taxiThrough = True))
262lhbpGates.add(Gate("R211", "2A", "S",
263 availableFn = getAvailableIf(othersAvailable = ["R212A"]),
264 taxiThrough = True))
265lhbpGates.add(Gate("R212", "2A", "S",
266 availableFn = getAvailableIf(othersAvailable = ["R212A"]),
267 taxiThrough = True))
268lhbpGates.add(Gate("R212A", "2A", "S",
269 availableFn = getAvailableIf(othersAvailable = ["R210", "R211", "R212"]),
270 taxiThrough = True))
271lhbpGates.addSpace()
272
273lhbpGates.add(Gate("R220", "2B", "S"))
274lhbpGates.add(Gate("R221", "2B", "S"))
275lhbpGates.add(Gate("R222", "2B", "S"))
276lhbpGates.add(Gate("R223", "2B", "S"))
277lhbpGates.addSpace()
278
279lhbpGates.add(Gate("R224", "2A", "S"))
280lhbpGates.add(Gate("R225", "2A", "S"))
281lhbpGates.add(Gate("R226", "2A", "S"))
282lhbpGates.add(Gate("R227", "2A", "S"))
283lhbpGates.addNewColumn()
284
285lhbpGates.add(Gate("R270", "2A", "S"))
286lhbpGates.add(Gate("R271", "2A", "S"))
287lhbpGates.add(Gate("R272", "2A", "S"))
288lhbpGates.add(Gate("R273", "2A", "S"))
289lhbpGates.add(Gate("R274", "2A", "S"))
290lhbpGates.add(Gate("R275", "2A", "S"))
291lhbpGates.add(Gate("R276", "2A", "S"))
292lhbpGates.add(Gate("R277", "2A", "S"))
293lhbpGates.add(Gate("R278", "2A", "S",
294 availableFn = getAvailableIf(othersAvailable = ["R278A"]),
295 taxiThrough = True))
296lhbpGates.add(Gate("R278A", "2A", "S",
297 availableFn = getAvailableIf(othersAvailable = ["R278", "R279"])))
298lhbpGates.add(Gate("R279", "2A", "S",
299 availableFn = getAvailableIf(othersAvailable = ["R278A"]),
300 taxiThrough = True))
Note: See TracBrowser for help on using the repository browser.