source: src/mlx/gui/weighthelp.py@ 1033:330058d37574

python3
Last change on this file since 1033:330058d37574 was 1033:330058d37574, checked in by István Váradi <ivaradi@…>, 2 years ago

Updates for the new crew and passenger handling (re #357)

File size: 19.6 KB
Line 
1
2from mlx.gui.common import *
3
4from mlx.i18n import xstr
5from mlx.checks import PayloadChecker
6from mlx.rpc import BookedFlight
7
8import mlx.const as const
9
10#-------------------------------------------------------------------------------
11
12## @package mlx.gui.weighthelp
13#
14# The weight calculation help tab.
15#
16# This module implements the tab containing the weight calculation help.
17
18#-------------------------------------------------------------------------------
19
20class WeightHelp(Gtk.VBox):
21 """The weight calculation help tab."""
22 @staticmethod
23 def _getMarkup(value, expectedValue = None, tolerance = None):
24 """Get the markup for the given value.
25
26 If it is too much different from the expected value, it will be
27 colored yellow (if within the tolerance), or red (if out of the tolerance)."""
28 markup = "%.0f" % (value,)
29 if expectedValue is not None and tolerance is not None:
30 colour = None
31 diff = abs(value - expectedValue)
32 if diff>tolerance: colour = "red"
33 elif (diff*10)>=tolerance: colour = "orange"
34 else: colour = "darkgreen"
35 if colour is not None:
36 markup = '<span foreground="' + colour + '">' + markup + '</span>'
37 return markup
38
39 def __init__(self, gui):
40 """Construct the tab."""
41 super(WeightHelp, self).__init__()
42
43 self._gui = gui
44
45 mainAlignment = Gtk.Alignment(xalign = 0.5, yalign = 0.5,
46 xscale = 1.0, yscale = 1.0)
47 mainAlignment.set_padding(padding_top = 4, padding_bottom = 4,
48 padding_left = 12, padding_right = 12)
49 self.add(mainAlignment)
50
51 self._mainBox = mainBox = Gtk.VBox()
52 mainAlignment.add(mainBox)
53
54 self._usingHelp = Gtk.CheckButton(xstr("weighthelp_usinghelp"))
55 self._usingHelp.set_use_underline(True)
56 self._usingHelp.set_tooltip_text(xstr("weighthelp_usinghelp_tooltip"))
57 self._usingHelp.connect("toggled", self._usingHelpToggled)
58 mainBox.pack_start(self._usingHelp, False, False, 4)
59
60
61 self._weightsTable = table = Gtk.Table(16, 5)
62 table.set_homogeneous(False)
63 table.set_row_spacings(4)
64 table.set_col_spacings(16)
65 alignment = Gtk.Alignment(xalign = 0.5, yalign = 0.5,
66 xscale = 0.0, yscale = 0.0)
67 alignment.add(table)
68 mainBox.pack_start(alignment, True, True, 4)
69
70 alignment = Gtk.Alignment(xalign = 1.0, yalign = 0.0,
71 xscale = 0.0, yscale = 0.0)
72 alignment.set_padding(padding_bottom = 16, padding_top = 0,
73 padding_left = 0, padding_right = 0)
74 label = Gtk.Label(xstr("weighthelp_header_calculated"))
75 label.set_use_markup(True)
76 # FIXME: should be a constant in common
77 label.set_justify(Gtk.Justification.CENTER)
78 alignment.add(label)
79 table.attach(alignment, 1, 2, 0, 1)
80
81 alignment = Gtk.Alignment(xalign = 1.0, yalign = 0.0,
82 xscale = 0.0, yscale = 0.0)
83 alignment.set_padding(padding_bottom = 16, padding_top = 0,
84 padding_left = 0, padding_right = 0)
85 button = Gtk.Button(xstr("weighthelp_header_simulator"))
86 button.set_tooltip_markup(xstr("weighthelp_header_simulator_tooltip"))
87 button.connect("clicked", self._fsButtonClicked)
88 label = button.get_child()
89 label.set_justify(Gtk.Justification.CENTER)
90 alignment.add(button)
91 table.attach(alignment, 3, 4, 0, 1)
92
93
94 self._crewLabel = Gtk.Label(xstr("weighthelp_crew") % ("99",))
95 alignment = Gtk.Alignment(xalign = 0.0, yalign = 0.5,
96 xscale = 0.0, yscale = 0.0)
97 alignment.add(self._crewLabel)
98 table.attach(alignment, 0, 1, 1, 2)
99
100 self._crewWeight = Gtk.Label("0")
101 alignment = Gtk.Alignment(xalign = 1.0, yalign = 0.5,
102 xscale = 0.0, yscale = 0.0)
103 alignment.add(self._crewWeight)
104 table.attach(alignment, 1, 2, 1, 2)
105
106 table.attach(Gtk.Label("kg"), 2, 3, 1, 2)
107
108 text = xstr("weighthelp_pax") % ("999",)
109 self._paxLabel = Gtk.Label(text)
110 self._paxLabel.set_width_chars(len(text))
111 self._paxLabel.set_alignment(0.0, 0.5)
112 alignment = Gtk.Alignment(xalign = 0.0, yalign = 0.5,
113 xscale = 0.0, yscale = 0.0)
114 alignment.add(self._paxLabel)
115 table.attach(alignment, 0, 1, 2, 3)
116
117 self._paxWeight = Gtk.Label("20000")
118 alignment = Gtk.Alignment(xalign = 1.0, yalign = 0.5,
119 xscale = 0.0, yscale = 0.0)
120 alignment.add(self._paxWeight)
121 table.attach(alignment, 1, 2, 2, 3)
122
123 table.attach(Gtk.Label("kg"), 2, 3, 2, 3)
124
125 label = Gtk.Label(xstr("weighthelp_baggage"))
126 alignment = Gtk.Alignment(xalign = 0.0, yalign = 0.5,
127 xscale = 0.0, yscale = 0.0)
128 alignment.add(label)
129 table.attach(alignment, 0, 1, 3, 4)
130
131 self._bagWeight = Gtk.Label("2000")
132 alignment = Gtk.Alignment(xalign = 1.0, yalign = 0.5,
133 xscale = 0.0, yscale = 0.0)
134 alignment.add(self._bagWeight)
135 table.attach(alignment, 1, 2, 3, 4)
136
137 table.attach(Gtk.Label("kg"), 2, 3, 3, 4)
138
139 label = Gtk.Label(xstr("weighthelp_cargo"))
140 alignment = Gtk.Alignment(xalign = 0.0, yalign = 0.5,
141 xscale = 0.0, yscale = 0.0)
142 alignment.add(label)
143 table.attach(alignment, 0, 1, 4, 5)
144
145 self._cargoWeight = Gtk.Label("2000")
146 alignment = Gtk.Alignment(xalign = 1.0, yalign = 0.5,
147 xscale = 0.0, yscale = 0.0)
148 alignment.add(self._cargoWeight)
149 table.attach(alignment, 1, 2, 4, 5)
150
151 table.attach(Gtk.Label("kg"), 2, 3, 4, 5)
152
153 label = Gtk.Label(xstr("weighthelp_mail"))
154 alignment = Gtk.Alignment(xalign = 0.0, yalign = 0.5,
155 xscale = 0.0, yscale = 0.0)
156 alignment.add(label)
157 table.attach(alignment, 0, 1, 5, 6)
158
159 self._mailWeight = Gtk.Label("2000")
160 alignment = Gtk.Alignment(xalign = 1.0, yalign = 0.5,
161 xscale = 0.0, yscale = 0.0)
162 alignment.add(self._mailWeight)
163 table.attach(alignment, 1, 2, 5, 6)
164
165 table.attach(Gtk.Label("kg"), 2, 3, 5, 6)
166
167 table.attach(Gtk.HSeparator(), 1, 2, 6, 7)
168
169 label = Gtk.Label("<b>" + xstr("weighthelp_payload") + "</b>")
170 label.set_use_markup(True)
171 alignment = Gtk.Alignment(xalign = 0.0, yalign = 0.5,
172 xscale = 0.0, yscale = 0.0)
173 alignment.add(label)
174 table.attach(alignment, 0, 1, 7, 8)
175
176 self._payload = Gtk.Label("<b>32000</b>")
177 self._payload.set_use_markup(True)
178 alignment = Gtk.Alignment(xalign = 1.0, yalign = 0.5,
179 xscale = 0.0, yscale = 0.0)
180 alignment.add(self._payload)
181 table.attach(alignment, 1, 2, 7, 8)
182
183 table.attach(Gtk.Label("kg"), 2, 3, 7, 8)
184
185 self._fsPayload = Gtk.Label("<b>32001</b>")
186 self._fsPayload.set_use_markup(True)
187 alignment = Gtk.Alignment(xalign = 1.0, yalign = 0.5,
188 xscale = 0.0, yscale = 0.0)
189 alignment.add(self._fsPayload)
190 table.attach(alignment, 3, 4, 7, 8)
191
192 table.attach(Gtk.Label("kg"), 4, 5, 7, 8)
193
194 label = Gtk.Label(xstr("weighthelp_dow"))
195 label.set_use_markup(True)
196 alignment = Gtk.Alignment(xalign = 0.0, yalign = 0.5,
197 xscale = 0.0, yscale = 0.0)
198 alignment.add(label)
199 table.attach(alignment, 0, 1, 8, 9)
200
201 self._dow = Gtk.Label("35000")
202 alignment = Gtk.Alignment(xalign = 1.0, yalign = 0.5,
203 xscale = 0.0, yscale = 0.0)
204 alignment.add(self._dow)
205 table.attach(alignment, 1, 2, 8, 9)
206
207 table.attach(Gtk.Label("kg"), 2, 3, 8, 9)
208
209 self._fsDOW = Gtk.Label("33012")
210 alignment = Gtk.Alignment(xalign = 1.0, yalign = 0.5,
211 xscale = 0.0, yscale = 0.0)
212 alignment.add(self._fsDOW)
213 table.attach(alignment, 3, 4, 8, 9)
214
215 table.attach(Gtk.Label("kg"), 4, 5, 8, 9)
216
217 table.attach(Gtk.HSeparator(), 1, 2, 9, 10)
218
219 table.attach(Gtk.HSeparator(), 3, 4, 9, 10)
220
221 label = Gtk.Label("<b>" + xstr("weighthelp_zfw") + "</b>")
222 label.set_use_markup(True)
223 alignment = Gtk.Alignment(xalign = 0.0, yalign = 0.5,
224 xscale = 0.0, yscale = 0.0)
225 alignment.add(label)
226 table.attach(alignment, 0, 1, 10, 11)
227
228 self._zfw = Gtk.Label("<b>122000</b>")
229 self._zfw.set_use_markup(True)
230 alignment = Gtk.Alignment(xalign = 1.0, yalign = 0.5,
231 xscale = 0.0, yscale = 0.0)
232 alignment.add(self._zfw)
233 table.attach(alignment, 1, 2, 10, 11)
234
235 table.attach(Gtk.Label("kg"), 2, 3, 10, 11)
236
237 self._fsZFW = Gtk.Label("<b>124000</b>")
238 self._fsZFW.set_use_markup(True)
239 alignment = Gtk.Alignment(xalign = 1.0, yalign = 0.5,
240 xscale = 0.0, yscale = 0.0)
241 alignment.add(self._fsZFW)
242 table.attach(alignment, 3, 4, 10, 11)
243
244 table.attach(Gtk.Label("kg"), 4, 5, 10, 11)
245
246 table.attach(Gtk.HSeparator(), 0, 5, 11, 12)
247
248 label = Gtk.Label(xstr("weighthelp_gross"))
249 label.set_use_markup(True)
250 alignment = Gtk.Alignment(xalign = 0.0, yalign = 0.5,
251 xscale = 0.0, yscale = 0.0)
252 alignment.add(label)
253 table.attach(alignment, 0, 1, 12, 13)
254
255 self._fsGross = Gtk.Label("124000")
256 alignment = Gtk.Alignment(xalign = 1.0, yalign = 0.5,
257 xscale = 0.0, yscale = 0.0)
258 alignment.add(self._fsGross)
259 table.attach(alignment, 3, 4, 12, 13)
260
261 table.attach(Gtk.Label("kg"), 4, 5, 12, 13)
262
263 label = Gtk.Label(xstr("weighthelp_mzfw"))
264 label.set_use_markup(True)
265 alignment = Gtk.Alignment(xalign = 0.0, yalign = 0.5,
266 xscale = 0.0, yscale = 0.0)
267 alignment.add(label)
268 table.attach(alignment, 0, 1, 13, 14)
269
270 self._mzfw = Gtk.Label("35000")
271 alignment = Gtk.Alignment(xalign = 1.0, yalign = 0.5,
272 xscale = 0.0, yscale = 0.0)
273 alignment.add(self._mzfw)
274 table.attach(alignment, 1, 2, 13, 14)
275
276 table.attach(Gtk.Label("kg"), 2, 3, 13, 14)
277
278 label = Gtk.Label(xstr("weighthelp_mtow"))
279 label.set_use_markup(True)
280 alignment = Gtk.Alignment(xalign = 0.0, yalign = 0.5,
281 xscale = 0.0, yscale = 0.0)
282 alignment.add(label)
283 table.attach(alignment, 0, 1, 14, 15)
284
285 self._mtow = Gtk.Label("35000")
286 alignment = Gtk.Alignment(xalign = 1.0, yalign = 0.5,
287 xscale = 0.0, yscale = 0.0)
288 alignment.add(self._mtow)
289 table.attach(alignment, 1, 2, 14, 15)
290
291 table.attach(Gtk.Label("kg"), 2, 3, 14, 15)
292
293 label = Gtk.Label(xstr("weighthelp_mlw"))
294 label.set_use_markup(True)
295 alignment = Gtk.Alignment(xalign = 0.0, yalign = 0.5,
296 xscale = 0.0, yscale = 0.0)
297 alignment.add(label)
298 table.attach(alignment, 0, 1, 15, 16)
299
300 self._mlw = Gtk.Label("35000")
301 alignment = Gtk.Alignment(xalign = 1.0, yalign = 0.5,
302 xscale = 0.0, yscale = 0.0)
303 alignment.add(self._mlw)
304 table.attach(alignment, 1, 2, 15, 16)
305
306 table.attach(Gtk.Label("kg"), 2, 3, 15, 16)
307
308 self.show_all()
309
310 def disable(self):
311 """Disable the widget."""
312 self._mainBox.set_sensitive(False)
313
314 def enable(self):
315 """Enable the widget."""
316 self._mainBox.set_sensitive(True)
317
318 def reset(self):
319 """Reset all calculated and FS data."""
320
321 self._usingHelp.set_active(False)
322 self._usingHelp.set_sensitive(True)
323 self._weightsTable.set_sensitive(False)
324
325 self._flightType = -1
326 self._dowCabinCrew = -1
327 self._cockpitCrew = -1
328 self._cabinCrew = -1
329 self._pax = -1
330 self._children = -1
331 self._infants = -1
332 self._bag = -1
333 self._cargo = -1
334 self._mail = -1
335 self._dowValue = -1
336 self._mzfwValue = -1
337 self._mtowValue = -1
338 self._mlwValue = -1
339
340 self._fsPayloadValue = -1
341 self._fsDOWValue = -1
342 self._fsZFWValue = -1
343 self._fsGrossValue = -1
344
345 self._setupCalculated()
346 self._setupFS()
347
348 def _setupCalculated(self):
349 """Setup the labels for the calculated values."""
350 crewWeight = self._getCrewWeight()
351 if crewWeight is None:
352 self._crewLabel.set_text(xstr("weighthelp_crew") % ("-",))
353 self._crewWeight.set_text("-")
354 else:
355 self._crewLabel.set_text(xstr("weighthelp_crew") %
356 (str(self._cockpitCrew) + "+" +
357 str(self._cabinCrew),))
358 self._crewWeight.set_text("%.0f" % (crewWeight,))
359
360 paxWeight = self._getPaxWeight()
361 if paxWeight<0:
362 self._paxLabel.set_text(xstr("weighthelp_pax") % ("-",))
363 self._paxWeight.set_text("-")
364 else:
365 self._paxLabel.set_text(xstr("weighthelp_pax") %
366 (str(self._pax) + "+" +
367 str(self._children) + "+" +
368 str(self._infants),))
369 self._paxWeight.set_text("%.0f" % (paxWeight,))
370
371 self._setWeightLabel(self._bagWeight, self._bag)
372
373 self._setWeightLabel(self._cargoWeight, self._cargo)
374
375 self._setWeightLabel(self._mailWeight, self._mail)
376
377 (payload, zfw) = self._calculateWeights()
378
379 self._setWeightLabel(self._payload, payload, bold = True)
380
381 self._setWeightLabel(self._dow, self._dowValue)
382
383 if zfw<0:
384 self._zfw.set_text("-")
385 else:
386 markup = "%.0f" % (zfw,)
387 if self._mzfwValue>0 and zfw>self._mzfwValue:
388 markup = '<span foreground="red">' + markup + '</span>'
389 markup = '<b>' + markup + '</b>'
390 self._zfw.set_markup(markup)
391
392 self._setWeightLabel(self._mzfw, self._mzfwValue)
393
394 self._setWeightLabel(self._mtow, self._mtowValue)
395
396 self._setWeightLabel(self._mlw, self._mlwValue)
397
398 def _setupFS(self):
399 if self._dowValue<0:
400 self._dow.set_text("-")
401 else:
402 self._dow.set_text("%.0f" % (self._dowValue,))
403
404 """Setup the labels for the FS values."""
405 (payload, zfw) = self._calculateWeights()
406
407 if self._fsPayloadValue<0:
408 self._fsPayload.set_text("-")
409 else:
410 markup = WeightHelp._getMarkup(self._fsPayloadValue, payload,
411 PayloadChecker.TOLERANCE)
412 self._fsPayload.set_markup("<b>" + markup + "</b>")
413
414 if self._fsDOWValue<0:
415 self._fsDOW.set_text("-")
416 else:
417 markup = WeightHelp._getMarkup(self._fsDOWValue, self._dowValue,
418 PayloadChecker.TOLERANCE)
419 self._fsDOW.set_markup(markup)
420
421 if self._fsZFWValue<0:
422 self._fsZFW.set_text("-")
423 else:
424 markup = WeightHelp._getMarkup(self._fsZFWValue, zfw,
425 PayloadChecker.TOLERANCE)
426 self._fsZFW.set_markup("<b>" + markup + "</b>")
427
428 self._setWeightLabel(self._fsGross, self._fsGrossValue)
429
430 def _getCrewWeight(self):
431 """Get the crew weight for the flight."""
432 if self._cockpitCrew>=0 and self._dowCabinCrew>=0 and self._cabinCrew>=0:
433 return (self._cabinCrew - self._dowCabinCrew) * const.WEIGHT_CABIN_CREW
434 else:
435 return None
436
437 def _getPaxWeight(self):
438 """Get the passenger weight for the flight."""
439 if self._flightType>=0 and self._pax>=0 and self._children>=0 and \
440 self._infants>=0:
441 return self._pax * \
442 (const.WEIGHT_PASSENGER_CHARTER
443 if self._flightType==BookedFlight.FLIGHT_TYPE_CHARTER
444 else const.WEIGHT_PASSENGER) + \
445 self._children * const.WEIGHT_CHILD + \
446 self._infants * const.WEIGHT_INFANT
447 else:
448 return -1
449
450 def _calculateWeights(self):
451 """Calculate the payload and the zero-fuel weight.
452
453 It returns a tuple with these two items. If any of the items cannot be
454 calculated, that is -1."""
455 crewWeight = self._getCrewWeight()
456 paxWeight = self._getPaxWeight()
457 if crewWeight is None or paxWeight<0 or \
458 self._bag<0 or self._cargo<0 or self._mail<0:
459 payload = -1
460 else:
461 payload = crewWeight + paxWeight + self._bag + self._cargo + self._mail
462
463 if payload<0 or self._dowValue<0:
464 zfw = -1
465 else:
466 zfw = payload + self._dowValue
467
468 return (payload, zfw)
469
470 def _usingHelpToggled(self, button):
471 """Called when the Using help button is toggled."""
472 assert self._usingHelp.get_active()
473 self._usingHelp.set_sensitive(False)
474
475 self._gui.logger.untimedMessage("The weight calculation help function was used by the pilot")
476
477 bookedFlight = self._gui.bookedFlight
478 self._flightType = bookedFlight.flightType
479 self._dowCabinCrew = bookedFlight.dowNumCabinCrew
480 self._cockpitCrew = self._gui.numCockpitCrew
481 self._cabinCrew = self._gui.numCabinCrew
482 self._pax = self._gui.numPassengers
483 self._children = self._gui.numChildren
484 self._infants = self._gui.numInfants
485 self._bag = self._gui.bagWeight
486 self._cargo = self._gui.cargoWeight
487 self._mail = self._gui.mailWeight
488 self._dowValue = bookedFlight.dow
489
490 aircraft = self._gui.flight.aircraft
491 self._mzfwValue = aircraft.mzfw
492 self._mtowValue = aircraft.mtow
493 self._mlwValue = aircraft.mlw
494
495 self._setupCalculated()
496 self._weightsTable.set_sensitive(True)
497
498 def _fsButtonClicked(self, button):
499 """Callback for the FS button being clicked."""
500 gui = self._gui
501 gui.beginBusy(xstr("weighthelp_busy"))
502 gui.simulator.requestWeights(self._handleWeights)
503
504 def _handleWeights(self, dow, payload, zfw, grossWeight):
505 """Handle the given weights."""
506 GObject.idle_add(self._processWeights, dow, payload, zfw, grossWeight)
507
508 def _processWeights(self, dow, payload, zfw, grossWeight):
509 """Process the given weights."""
510 self._gui.endBusy()
511 if self._usingHelp.get_active():
512 self._fsPayloadValue = payload
513 self._fsDOWValue = dow
514 self._fsZFWValue = zfw
515 self._fsGrossValue = grossWeight
516 self._setupFS()
517
518 def _setWeightLabel(self, label, weight, bold = False):
519 """Set the given weight label to the given weight."""
520 if weight<0:
521 label.set_text("-")
522 else:
523 markup = "%.0f" % (weight,)
524 if bold: markup = "<b>" + markup + "</b>"
525 label.set_markup(markup)
526
527
Note: See TracBrowser for help on using the repository browser.