source: src/mlx/acft.py@ 799:959b8a49cde5

Last change on this file since 799:959b8a49cde5 was 799:959b8a49cde5, checked in by István Váradi <ivaradi@…>, 8 years ago

Some weights differing from the type default are set up for the appropriate tail numbers

File size: 48.1 KB
RevLine 
[298]1
2import const
[619]3import gates
[298]4import checks
5import fs
[384]6from i18n import xstr
[298]7import util
8
9import sys
10import time
11import traceback
12
13from collections import deque
14
15#---------------------------------------------------------------------------------------
16
[297]17## @package mlx.acft
18#
19# The simulator-independent aircraft classes.
20#
21# This module contains the aircraft classes that contain some general data
22# about each aircraft type in the MAVA Fleet. The base class, \ref Aircraft
23# also implements some parts of the logging and traces some data. The classes
24# are also responsible for creating the \ref mlx.checks "checkers". Most of
25# them are created by the \ref Aircraft class' constructor, but there can be
26# type-specific differences. For example the lights are different for different
27# types, so there is a \ref Aircraft._appendLightsLoggers "function" which can
28# be reimplemented in child classes, if needed. This class maintains also the
29# \ref SmoothedValue "smoothed values" of the IAS and the VS and set these
30# values in the \ref mlx.fs.AircraftState "aircraft state" when it is received
31# from the simulator.
[4]32
33#---------------------------------------------------------------------------------------
34
[512]35# Derate type: no derate possible
36DERATE_NONE = 0
37
38# Derate type: Boeing, i.e. a percentage value.
39# For logging, the percentage value is expected as a string (i.e. whatever the
40# pilot enters into the text field).
41DERATE_BOEING = 1
42
43# Derate type: EPR, i.e. an EPR value.
44# For logging, the EPR value is expected as a string (i.e. whatever the pilot
45# enters into the text field).
46DERATE_EPR = 2
47
48# Derate type: Tupolev, i.e. nominal or takeoff
49# For logging, one of the DERATE_TUPOLEV_xxx values are expected.
50DERATE_TUPOLEV = 3
51
52# Tupolev derate value: nominal
53DERATE_TUPOLEV_NOMINAL = 1
54
55# Tupolev derate value: takeoff
56DERATE_TUPOLEV_TAKEOFF = 2
57
58# Derate type: BAe-146, i.e. enabled or not
59# For logging, a boolean is expected.
60DERATE_B462 = 4
61
62#---------------------------------------------------------------------------------------
63
[197]64class SmoothedValue(object):
65 """A smoothed value."""
66 def __init__(self):
67 """Construct the value."""
68 self._deque = deque()
69 self._sum = 0
70
71 def add(self, length, value):
72 """Add the given value and smooth with the given length."""
73 dequeLength = len(self._deque)
74 while dequeLength>=length:
75 self._sum -= self._deque.popleft()
76 dequeLength -= 1
77
78 self._sum += value
79 self._deque.append(value)
80
81 def get(self):
82 """Get the average."""
83 return self._sum / len(self._deque)
[331]84
[4]85#---------------------------------------------------------------------------------------
86
[709]87class SimBriefData(object):
88 """Data to be used when creating SimBrief briefings."""
89 def __init__(self, climbProfiles, cruiseProfiles, descentProfiles):
90 """Construct the SimBrief data with the given profiles."""
91 self.climbProfiles = climbProfiles
92 self.cruiseProfiles = cruiseProfiles
93 self.descentProfiles = descentProfiles
94
95#---------------------------------------------------------------------------------------
96
[4]97class Aircraft(object):
98 """Base class for aircraft."""
[8]99 @staticmethod
[798]100 def create(flight, bookedFlight):
[8]101 """Create an aircraft instance for the type in the given flight."""
[798]102 acft = _classes[flight.aircraftType](flight)
103 acft.setBookedFlight(bookedFlight)
104 return acft
[8]105
[592]106 def __init__(self, flight, minLandingFuel = None,
107 recommendedLandingFuel = None):
[4]108 """Construct the aircraft for the given type."""
[8]109 self._flight = flight
[591]110 self._minLandingFuel = minLandingFuel
[592]111 self._recommendedLandingFuel = recommendedLandingFuel
[369]112
113 self._name = None
114 self._modelName = None
115
[4]116 self._aircraftState = None
[331]117
[9]118 self._maxVS = -10000.0
119 self._minVS = 10000.0
[4]120
[101]121 self._v1r2LineIndex = None
[384]122 self._derateLineID = None
[391]123 self._takeoffAntiIceLineID = None
[96]124 self._vrefLineIndex = None
[391]125 self._landingAntiIceLineID = None
[96]126
[117]127 self.humanWeight = 82.0
128
[598]129 self.initialClimbSpeedAltitude = 1500
130 self.reverseMinSpeed = 50
[360]131
[644]132 self.hasStrobeLight = True
133
[611]134 self.maxTakeOffPitch = 15.0
135 self.maxTouchDownPitch = 15.0
[624]136 self.brakeCoolTime = 10.0
[611]137
[709]138 self.simBriefData = None
139
[8]140 self._checkers = []
141
[197]142 config = flight.config
[11]143 # Loggers
144
[8]145 self._checkers.append(checks.StageChecker())
[9]146 self._checkers.append(checks.TakeOffLogger())
[8]147
148 self._checkers.append(checks.AltimeterLogger())
[321]149
[366]150 self._ilsLogger = checks.ILSLogger()
151 self._checkers.append(self._ilsLogger)
[321]152 self._nav1Logger = checks.NAV1Logger()
153 self._checkers.append(self._nav1Logger)
154 self._nav2Logger = checks.NAV2Logger()
155 self._checkers.append(self._nav2Logger)
156
157 self._adf1Logger = checks.ADF1Logger()
158 self._checkers.append(self._adf1Logger)
159 self._adf2Logger = checks.ADF2Logger()
160 self._checkers.append(self._adf2Logger)
[331]161
[8]162 self._checkers.append(checks.SquawkLogger())
163
[211]164 self._appendLightsLoggers()
[8]165
166 self._checkers.append(checks.FlapsLogger())
167
168 self._checkers.append(checks.GearsLogger())
[601]169 self._checkers.append(checks.InitialClimbSpeedLogger())
[9]170 self._checkers.append(checks.CruiseSpeedLogger())
[10]171 self._checkers.append(checks.SpoilerLogger())
[338]172 self._checkers.append(checks.APLogger())
[9]173
[197]174 if config.isMessageTypeFS(const.MESSAGETYPE_VISIBILITY):
[134]175 self._checkers.append(checks.VisibilityChecker())
176
[139]177 # FIXME: we should have a central data model object, and not collect
178 # the data from the GUI. However, some pieces of data (e.g. V-speeds,
179 # etc. that is entered into the GUI) *should* be a part of the GUI and
180 # queried from it, so the model should have a reference to the GUI as
181 # well and access such data via the GUI!
[215]182 if config.onlineACARS and flight.loggedIn and not flight.entranceExam:
[139]183 self._checkers.append(checks.ACARSSender(flight._gui))
184
[11]185 # Fault checkers
[211]186
187 self._appendLightsCheckers()
[11]188
[335]189 self._checkers.append(checks.TransponderChecker())
190
[11]191 self._checkers.append(checks.BankChecker())
192
193 self._checkers.append(checks.FlapsRetractChecker())
194 self._checkers.append(checks.FlapsSpeedLimitChecker())
195
196 self._checkers.append(checks.GearsDownChecker())
197 self._checkers.append(checks.GearSpeedLimitChecker())
198
199 self._checkers.append(checks.GLoadChecker())
200
201 self._checkers.append(checks.MLWChecker())
202 self._checkers.append(checks.MTOWChecker())
203 self._checkers.append(checks.MZFWChecker())
204 self._checkers.append(checks.PayloadChecker())
205
[539]206 self._checkers.append(checks.SpeedChecker())
[11]207 self._checkers.append(checks.VSChecker())
[197]208
[447]209 timeout = 30.0 + config.realIASSmoothingLength - 1
[622]210 self._checkers.append(checks.OverspeedChecker(faultTimeout = timeout))
[331]211
[11]212 self._checkers.append(checks.StallChecker())
213
214 self._checkers.append(checks.PitotChecker())
[331]215
[598]216 self._checkers.append(checks.ReverserLogger())
[11]217 self._checkers.append(checks.ReverserChecker())
218
[273]219 if flight.aircraftType is not None and config.enableApproachCallouts:
220 approachCallouts = flight.config.getApproachCallouts(flight.aircraftType)
221 if approachCallouts:
222 self._checkers.append(checks.ApproachCalloutsPlayer(approachCallouts))
223
[197]224 self._smoothedIAS = SmoothedValue()
225 self._smoothedVS = SmoothedValue()
226
[4]227 @property
228 def type(self):
229 """Get the type of the aircraft."""
[8]230 return self._flight.aircraftType
231
232 @property
233 def flight(self):
234 """Get the flight the aircraft belongs to."""
235 return self._flight
[4]236
[8]237 @property
[592]238 def minLandingFuel(self):
239 """Get the minimum acceptable amount of the landing fuel."""
240 return self._minLandingFuel
241
242 @property
243 def recommendedLandingFuel(self):
244 """Get the recommended amount of the landing fuel."""
245 return self._recommendedLandingFuel
246
247 @property
[8]248 def logger(self):
249 """Get the logger to use for the aircraft."""
250 return self._flight.logger
251
[139]252 @property
253 def state(self):
254 """Get the current aircraft state."""
255 return self._aircraftState
[241]256
257 @property
258 def speedInKnots(self):
259 """Indicate if the speed is in knots.
260
261 This default implementation returns True."""
262 return True
[304]263
264 @property
[635]265 def aglInFeet(self):
266 """Indicate if AGL altitudes are to be logged in feet.
267
268 This default implementation returns True."""
269 return True
270
271 @property
[304]272 def timestamp(self):
273 """Get the timestamp of the current state."""
274 return None if self._aircraftState is None \
275 else self._aircraftState.timestamp
[331]276
[384]277 @property
[512]278 def derateType(self):
279 """Get the derate type for this aircraft.
280
281 This default implementation returns DERATE_NONE."""
282 return DERATE_NONE
[384]283
[798]284 def setBookedFlight(self, bookedFlight):
285 """Update the aircraft based on the booked flight data (e.g. tail number).
286
287 This default implementation does nothing."""
288
[512]289 def getDerateLine(self, value):
290 """Get the log line for the given derate value.
291
292 It uses the the derate type and produces the standard message for
293 each. This children need not override it, although they can."""
294 dt = self.derateType
[384]295
[512]296 if dt==DERATE_BOEING:
297 return "Derate calculated by the pilot: %s %%" % \
298 ("-" if value is None else value,)
299 elif dt==DERATE_EPR:
300 return "EPR calculated by the pilot: %s" % \
301 ("-" if value is None else value,)
302 elif dt==DERATE_TUPOLEV:
303 return "Thrust setting calculated by the pilot: %s" % \
304 ("-" if value is None else
305 "nominal" if value==DERATE_TUPOLEV_NOMINAL else "takeoff",)
306 elif dt==DERATE_B462:
307 return "Derate setting: %s" % \
308 ("-" if value is None else "enabled" if value else "disabled",)
309 elif dt!=DERATE_NONE:
310 print "mlx.acft.getDerateLine: invalid derate type: " + dt
[384]311
312 return None
313
[11]314 def getFlapsSpeedLimit(self, flaps):
315 """Get the speed limit for the given flaps setting."""
316 return self.flapSpeedLimits[flaps] if flaps in self.flapSpeedLimits \
317 else None
318
[8]319 def modelChanged(self, timestamp, aircraftName, modelName):
[4]320 """Called when the simulator's aircraft changes."""
[369]321 self._name = aircraftName
322 self._modelName = modelName
323 if self._flight.stage is not None:
324 self._logNameAndModel(timestamp)
[4]325
326 def handleState(self, aircraftState):
[197]327 """Called when the state of the aircraft changes.
328
329 This is the function that the simulator calls directly with the new
330 state."""
[274]331 try:
332 config = self._flight.config
[197]333
[274]334 self._smoothedIAS.add(config.realIASSmoothingLength, aircraftState.ias)
335 aircraftState.smoothedIAS = self._smoothedIAS.get()
336
337 self._smoothedVS.add(config.realVSSmoothingLength, aircraftState.vs)
338 aircraftState.smoothedVS = self._smoothedVS.get()
[197]339
[274]340 for checker in self._checkers:
341 try:
342 checker.check(self._flight, self, self._flight.logger,
343 self._aircraftState, aircraftState)
344 except:
345 print >> sys.stderr, "Checker", checker, "failed"
346 traceback.print_exc()
[7]347
[274]348 self._flight.handleState(self._aircraftState, aircraftState)
[89]349
[274]350 self._maxVS = max(self._maxVS, aircraftState.vs)
351 self._minVS = min(self._minVS, aircraftState.vs)
352 except:
353 print >> sys.stderr, "Failed to handle the state"
354 traceback.print_exc()
355 finally:
356 self._aircraftState = aircraftState
[331]357
[8]358 def setStage(self, aircraftState, newStage):
359 """Set the given stage as the new one and do whatever should be
360 done."""
[369]361 if newStage==const.STAGE_BOARDING:
362 self._logNameAndModel(aircraftState.timestamp)
363
[624]364 oldStage = self._flight.stage
365
[9]366 if self._flight.setStage(aircraftState.timestamp, newStage):
367 if newStage==const.STAGE_PUSHANDTAXI:
368 self.logger.message(aircraftState.timestamp, "Block time start")
[274]369 self._flight.logFuel(aircraftState)
[331]370 self.logger.message(aircraftState.timestamp,
[313]371 "ZFW: %.2f kg" % (aircraftState.zfw))
[134]372 flight = self._flight
373 if flight.v1 is None or flight.vr is None or flight.v2 is None:
374 fs.sendMessage(const.MESSAGETYPE_HELP,
375 "Don't forget to set the takeoff V-speeds!",
376 5)
[9]377 elif newStage==const.STAGE_TAKEOFF:
[624]378 if oldStage == const.STAGE_RTO and self._flight.hasRTO:
379 rtoState = self._flight.rtoState
380 if (aircraftState.timestamp - rtoState.timestamp) < \
381 (self.brakeCoolTime * 60.0):
382 self.logger.fault("brakeCoolTime",
383 aircraftState.timestamp,
384 "Did not cool the brakes for at least %.f minutes after the RTO" % (self.brakeCoolTime,),
385 15.0)
[241]386 self.logger.message(aircraftState.timestamp,
387 "Flight time start")
[331]388 self.logger.message(aircraftState.timestamp,
[9]389 "Takeoff weight: %.0f kg, MTOW: %.0f kg" % \
390 (aircraftState.grossWeight, self.mtow))
[409]391 self._logQNH(aircraftState)
[9]392 self.logger.message(aircraftState.timestamp,
[333]393 "Wind %03.0f/%.0f" % \
[331]394 (aircraftState.windDirection,
[9]395 aircraftState.windSpeed))
[321]396 self._logRadios(aircraftState)
[345]397 self._logV1R2(aircraftState)
[384]398 self._logDerate(aircraftState)
[391]399 self._logTakeoffAntiIce(aircraftState)
[321]400 elif newStage==const.STAGE_DESCENT or newStage==const.STAGE_LANDING:
401 self._logRadios(aircraftState)
[409]402 if newStage==const.STAGE_LANDING:
403 self._logQNH(aircraftState)
[634]404 elif newStage==const.STAGE_GOAROUND:
405 from logger import Logger
406 self._flight.handleFault("goaround",
407 aircraftState.timestamp,
408 "Go-around detected, please, explain!",
409 Logger.NO_SCORE)
[9]410 elif newStage==const.STAGE_TAXIAFTERLAND:
[184]411 flight = self._flight
412 bookedFlight = flight.bookedFlight
413 config = flight.config
[136]414 if config.onlineGateSystem and \
[215]415 flight.loggedIn and \
[184]416 not flight.entranceExam and \
[136]417 bookedFlight.arrivalICAO=="LHBP" and \
418 config.isMessageTypeFS(const.MESSAGETYPE_GATE_SYSTEM):
[134]419 self._flight.getFleet(callback = self._fleetRetrieved,
420 force = True)
[9]421 self.logger.message(aircraftState.timestamp, "Flight time end")
[274]422 self._flight.logFuel(aircraftState)
[591]423 if self._minLandingFuel is not None and \
424 aircraftState.totalFuel<self._minLandingFuel:
[597]425 self._flight.handleFault(self.__class__,
426 aircraftState.timestamp,
427 "The amount of the landing fuel is less than the minimum for this type: %ukgs (possible NO GO!)" %
428 (self._minLandingFuel,), 0)
[9]429 self.logger.message(aircraftState.timestamp,
430 "Landing weight: %.0f kg, MLW: %.0f" % \
431 (aircraftState.grossWeight, self.mlw))
432 self.logger.message(aircraftState.timestamp,
433 "Vertical speed range: %.0f..%.0f feet/min" % \
[12]434 (self._minVS, self._maxVS))
[359]435 # elif newStage==const.STAGE_PARKING:
436 # self.logger.message(aircraftState.timestamp, "Block time end")
[89]437 elif newStage==const.STAGE_END:
438 flightLength = self._flight.flightTimeEnd - self._flight.flightTimeStart
[359]439 self.logger.message(aircraftState.timestamp, "Block time end")
[89]440 self.logger.message(aircraftState.timestamp,
441 "Flight time: " +
442 util.getTimeIntervalString(flightLength))
443 self.logger.message(aircraftState.timestamp,
444 "Flown distance: %.2f NM" % \
[331]445 (self._flight.flownDistance,))
[89]446 blockLength = self._flight.blockTimeEnd - self._flight.blockTimeStart
447 self.logger.message(aircraftState.timestamp,
448 "Block time: " +
449 util.getTimeIntervalString(blockLength))
[8]450
[9]451 def prepareFlare(self):
452 """Called when it is detected that we will soon flare.
[8]453
454 On the first call, it should start monitoring some parameters more
455 closely to determine flare time."""
[9]456 self.flight.simulator.startFlare()
457
[331]458 def flareStarted(self, windSpeed, windDirection, visibility,
[9]459 flareStart, flareStartFS):
460 """Called when the flare has started."""
461 self.logger.message(self._aircraftState.timestamp, "The flare has begun")
462 self.logger.message(self._aircraftState.timestamp,
[333]463 "Wind %03.0f/%.0f" % \
[9]464 (windDirection, windSpeed))
465 self.logger.message(self._aircraftState.timestamp,
466 "Visibility: %.0f metres" % (visibility,))
[409]467 self._logQNH(self._aircraftState)
[101]468 self._logVRef()
[391]469 self._logLandingAntiIce(self._aircraftState)
[9]470 self.flight.flareStarted(flareStart, flareStartFS)
[134]471 fs.sendMessage(const.MESSAGETYPE_INFORMATION, "Flare-time", 3)
[331]472
[9]473 def flareFinished(self, flareEnd, flareEndFS, tdRate, tdRateCalculatedByFS,
474 ias, pitch, bank, heading):
475 """Called when the flare has finished."""
476 (flareTimeFromFS, flareTime) = self.flight.flareFinished(flareEnd,
[170]477 flareEndFS,
478 tdRate)
[9]479 self.logger.message(self._aircraftState.timestamp,
[153]480 "Flaretime: %.3f (from %s)" % \
[331]481 (flareTime,
[9]482 "the simulator" if flareTimeFromFS else "real time",))
483 self.logger.message(self._aircraftState.timestamp,
484 "Touchdown rate: %.0f feet/min" % (tdRate,))
485 self.logger.message(self._aircraftState.timestamp,
486 "Touchdown rate was calculated by the %s" % \
487 ("simulator" if tdRateCalculatedByFS else "logger",))
[241]488 flight = self._flight
[9]489 self.logger.message(self._aircraftState.timestamp,
[241]490 "Touchdown speed: %.0f %s" % \
491 (flight.speedFromKnots(ias),
492 flight.getEnglishSpeedUnit()))
[9]493 self.logger.message(self._aircraftState.timestamp,
494 "Touchdown pitch: %.1f degrees" % (pitch,))
495 self.logger.message(self._aircraftState.timestamp,
496 "Touchdown bank: %.1f degrees" % (bank,))
497 self.logger.message(self._aircraftState.timestamp,
498 "Touchdown heading: %03.0f degrees" % (heading,))
[331]499 self.logger.message(self._aircraftState.timestamp,
[340]500 "CG: %.1f%%" % \
[271]501 (self._aircraftState.cog*100.0,))
[8]502
[611]503 if abs(pitch)>self.maxTouchDownPitch:
504 self._flight.handleNoGo("TDPitch", self._aircraftState.timestamp,
505 "Touchdown pitch higher than aircraft maximum (%.2f)" % \
506 (self.maxTouchDownPitch,),
507 "TD TAILSTRIKE NO GO")
508
[8]509 def cancelFlare(self):
510 """Cancel flare, if it has started."""
[9]511 self.flight.simulator.cancelFlare()
[8]512
513 def checkFlightEnd(self, aircraftState):
514 """Check if the end of the flight has arrived.
515
516 This default implementation checks the N1 values, but for
517 piston-powered aircraft you need to check the RPMs."""
518 for n1 in aircraftState.n1:
519 if n1>=0.5: return False
520 return True
521
[101]522 def updateV1R2(self):
523 """Update the V1, Vr and V2 values from the flight, if the these values
524 have already been logged."""
525 if self._v1r2LineIndex is not None:
526 self._logV1R2()
527
[384]528 def updateDerate(self):
529 """Update the derate value from the flight, if the these values
530 have already been logged."""
531 if self._derateLineID is not None:
532 self._logDerate()
533
[391]534 def updateTakeoffAntiIce(self):
535 """Update the take-off anti-ice setting."""
536 if self._takeoffAntiIceLineID is not None:
537 self._logTakeoffAntiIce()
538
[211]539 def _appendLightsLoggers(self):
540 """Append the loggers needed for the lights.
541
542 This default implementation adds the loggers for the anti-collision
543 lights, the landing lights, the strobe lights and the NAV lights."""
544 self._checkers.append(checks.AnticollisionLightsLogger())
545 self._checkers.append(checks.LandingLightsLogger())
546 self._checkers.append(checks.StrobeLightsLogger())
547 self._checkers.append(checks.NavLightsLogger())
548
549 def _appendLightsCheckers(self):
550 """Append the checkers needed for the lights.
551
552 This default implementation adds the checkers for the anti-collision
553 lights, the landing lights, the strobe lights and the NAV lights."""
554 self._checkers.append(checks.AntiCollisionLightsChecker())
555 self._checkers.append(checks.LandingLightsChecker())
556 self._checkers.append(checks.NavLightsChecker())
557 self._checkers.append(checks.StrobeLightsChecker())
558
[241]559 def _speedToLog(self, speed):
560 """Convert the given speed (being either None or expressed in the
561 flight's speed unit into a string."""
562 if speed is None:
563 return "-"
564 else:
565 return str(speed) + " " + self._flight.getEnglishSpeedUnit()
566
[345]567 def _logV1R2(self, state = None):
[101]568 """Log the V1, Vr and V2 value either newly, or by updating the
569 corresponding line."""
[526]570 message = "Calc. TO speeds: V1: %s, VR: %s, V2: %s" % \
[241]571 (self._speedToLog(self._flight.v1),
572 self._speedToLog(self._flight.vr),
573 self._speedToLog(self._flight.v2))
[101]574
575 if self._v1r2LineIndex is None:
[345]576 if state is None:
577 state = self._aircraftState
[101]578 self._v1r2LineIndex = \
[345]579 self.logger.message(state.timestamp, message)
[101]580 else:
581 self.logger.updateLine(self._v1r2LineIndex, message)
582
[384]583 def _logDerate(self, state = None):
584 """Log the derate values either newly or by updating the corresponding
585 line."""
[512]586 dt = self.derateType
587 if dt==DERATE_NONE:
[384]588 return
589
[512]590 message = self.getDerateLine(self._flight.derate)
591 if message is not None:
592 if self._derateLineID is None:
593 if state is None:
594 state = self._aircraftState
595 self._derateLineID = \
596 self.logger.message(state.timestamp, message)
597 else:
598 self.logger.updateLine(self._derateLineID, message)
[384]599
[391]600 def _logTakeoffAntiIce(self, state = None):
601 """Log the take-off anti-ice setting either newly or by updating the
602 corresponding line."""
603 antiIceOn = self._flight.takeoffAntiIceOn
604 if state is not None:
605 antiIceOn = antiIceOn or state.antiIceOn is True
606 self._flight.takeoffAntiIceOn = antiIceOn
607
608 message = "Anti-ice was turned %s" % \
609 ("ON" if antiIceOn else "OFF")
610
611 if self._takeoffAntiIceLineID is None:
612 if state is None:
613 state = self._aircraftState
614 self._takeoffAntiIceLineID = \
615 self.logger.message(state.timestamp, message)
616 else:
617 self.logger.updateLine(self._takeoffAntiIceLineID, message)
618
[96]619 def updateVRef(self):
620 """Update the Vref value from the flight, if the Vref value has already
621 been logged."""
622 if self._vrefLineIndex is not None:
623 self._logVRef()
624
625 def _logVRef(self):
626 """Log the Vref value either newly, or by updating the corresponding
627 line."""
628 message = "VRef speed calculated by the pilot: %s" % \
[241]629 (self._speedToLog(self._flight.vref),)
[96]630 if self._vrefLineIndex is None:
631 self._vrefLineIndex = \
632 self.logger.message(self._aircraftState.timestamp, message)
633 else:
634 self.logger.updateLine(self._vrefLineIndex, message)
635
[391]636 def updateLandingAntiIce(self):
637 """Update the landing anti-ice setting."""
638 if self._landingAntiIceLineID is not None:
639 self._logLandingAntiIce()
640
641 def _logLandingAntiIce(self, state = None):
642 """Log the landing anti-ice setting either newly or by updating the
643 corresponding line."""
644 antiIceOn = self._flight.landingAntiIceOn
645 if state is not None:
646 antiIceOn = antiIceOn or state.antiIceOn is True
647 self._flight.landingAntiIceOn = antiIceOn
648
649 message = "Anti-ice was turned %s" % \
650 ("ON" if antiIceOn else "OFF")
651
652 if self._landingAntiIceLineID is None:
653 if state is None:
654 state = self._aircraftState
655 self._landingAntiIceLineID = \
656 self.logger.message(state.timestamp, message)
657 else:
658 self.logger.updateLine(self._landingAntiIceLineID, message)
659
[134]660 def _fleetRetrieved(self, fleet):
661 """Callback for the fleet retrieval result."""
662 if fleet is not None:
663 gateList = ""
664 occupiedGateNumbers = fleet.getOccupiedGateNumbers()
[619]665 for gate in gates.lhbpGates.gates:
666 if gate.isAvailable(gates.lhbpGates, occupiedGateNumbers):
[134]667 if gateList: gateList += ", "
[619]668 gateList += gate.number
[134]669 fs.sendMessage(const.MESSAGETYPE_GATE_SYSTEM,
670 "Free gates: " + gateList, 20)
[331]671
[134]672
[321]673 def _logRadios(self, aircraftState):
674 """Log the radios from the given aircraft state."""
675 flight = self._flight
676 logger = flight.logger
677
[366]678 self._ilsLogger.forceLog(flight, logger, aircraftState)
[321]679 self._nav1Logger.forceLog(flight, logger, aircraftState)
680 self._nav2Logger.forceLog(flight, logger, aircraftState)
[329]681 self._adf1Logger.forceLog(flight, logger, aircraftState)
682 self._adf2Logger.forceLog(flight, logger, aircraftState)
[321]683
[409]684 def _logQNH(self, aircraftState):
685 """Log the current QNH along with the altimeter setting."""
686 self.logger.message(aircraftState.timestamp,
687 "QNH: %.2f hPa, altimeter: %.2f hPa" % \
688 (aircraftState.qnh, aircraftState.altimeter))
689
[369]690 def _logNameAndModel(self, timestamp):
691 """Log the aircraft's name and model with taking the timestamp from the
692 given state."""
693 self._flight.logger.message(timestamp,
694 "Aircraft: name='%s', model='%s'" % \
695 (self._name, self._modelName))
696
[4]697#---------------------------------------------------------------------------------------
[7]698
699class Boeing737(Aircraft):
700 """Base class for the various aircraft in the Boeing 737 family.
701
702 The aircraft type-specific values in the aircraft state have the following
703 structure:
[140]704 - fuel: left, centre, right
[7]705 - n1: left, right
[331]706 - reverser: left, right"""
[592]707 def __init__(self, flight, minLandingFuel = 2500,
708 recommendedLandingFuel = 3500):
709 super(Boeing737, self).__init__(flight,
710 minLandingFuel = minLandingFuel,
711 recommendedLandingFuel =
712 recommendedLandingFuel)
[95]713
[9]714 self.gearSpeedLimit = 270
715 self.flapSpeedLimits = { 1 : 260,
716 2 : 260,
717 5 : 250,
718 10 : 210,
719 15 : 200,
720 25 : 190,
721 30 : 175,
722 40 : 162 }
[7]723
[384]724 @property
[512]725 def derateType(self):
726 """Get the derate type for this type."""
727 return DERATE_BOEING
[384]728
[7]729#---------------------------------------------------------------------------------------
730
731class B736(Boeing737):
732 """Boeing 737-600 aircraft."""
[8]733 def __init__(self, flight):
734 super(B736, self).__init__(flight)
[9]735 self.dow = 38307
736 self.mtow = 58328
737 self.mlw = 54657
738 self.mzfw = 51482
[611]739 self.maxTakeOffPitch = 16.2
740 self.maxTouchDownPitch = 14.7
[709]741 self.simBriefData = SimBriefData(["250/280/78"],
742 ["CI", "M75", "M78", "M79", "M80", "LRC"],
743 ["78/280/250"])
[7]744
745#---------------------------------------------------------------------------------------
746
747class B737(Boeing737):
748 """Boeing 737-700 aircraft."""
[8]749 def __init__(self, flight):
750 super(B737, self).__init__(flight)
[9]751 self.dow = 39250
752 self.mtow = 61410
753 self.mlw = 58059
754 self.mzfw = 54657
[611]755 self.maxTakeOffPitch = 14.7
756 self.maxTouchDownPitch = 13.2
[709]757 self.simBriefData = SimBriefData(["250/280/78"],
758 ["CI", "M75", "M78", "M79", "M80", "LRC"],
759 ["78/280/250", "78/250/250"])
[7]760
761#---------------------------------------------------------------------------------------
762
763class B738(Boeing737):
764 """Boeing 737-800 aircraft."""
[8]765 def __init__(self, flight):
766 super(B738, self).__init__(flight)
[9]767 self.dow = 42690
[797]768 self.mtow = 71791
[9]769 self.mlw = 65317
770 self.mzfw = 61688
[611]771 self.maxTakeOffPitch = 11
772 self.maxTouchDownPitch = 9.5
[709]773 self.simBriefData = SimBriefData(["250/280/78"],
774 ["CI", "M76", "M78", "M79", "M80", "LRC"],
775 ["78/280/250", "78/250/250"])
[9]776
777#---------------------------------------------------------------------------------------
778
779class B738Charter(B738):
780 """Boeing 737-800 aircraft used for charters."""
781 def __init__(self, flight):
782 super(B738Charter, self).__init__(flight)
783 self.mtow = 77791
[709]784 self.simBriefData = SimBriefData(["AUTO"],
785 ["280/M74"],
786 ["AUTO"])
[7]787
788#---------------------------------------------------------------------------------------
789
[591]790class Boeing737CL(Boeing737):
791 """Base class for the various aircraft in the Boeing 737 Classic family."""
792 def __init__(self, flight):
[592]793 super(Boeing737CL, self).__init__(flight, minLandingFuel = 3500,
794 recommendedLandingFuel = None)
[591]795
796#---------------------------------------------------------------------------------------
797
[790]798class B732(Boeing737CL):
799 """Boeing 737-200 aircraft."""
800 def __init__(self, flight):
801 super(B732, self).__init__(flight)
[796]802 self.dow = 27646
803 self.mtow = 52390
804 self.mlw = 46720
805 self.mzfw = 43091
806 self.maxTakeOffPitch = 15.5
807 self.maxTouchDownPitch = 15.5
[790]808
809#---------------------------------------------------------------------------------------
810
[591]811class B733(Boeing737CL):
[7]812 """Boeing 737-300 aircraft."""
[8]813 def __init__(self, flight):
814 super(B733, self).__init__(flight)
[797]815 self.dow = 32900
816 self.mtow = 56472
817 self.mlw = 51710
818 self.mzfw = 47625
[611]819 self.maxTakeOffPitch = 13.4
820 self.maxTouchDownPitch = 12.0
[7]821
822#---------------------------------------------------------------------------------------
823
[591]824class B734(Boeing737CL):
[7]825 """Boeing 737-400 aircraft."""
[8]826 def __init__(self, flight):
827 super(B734, self).__init__(flight)
[797]828 self.dow = 35100
829 self.mtow = 62822
830 self.mlw = 54885
831 self.mzfw = 51256
[611]832 self.maxTakeOffPitch = 11.4
833 self.maxTouchDownPitch = 10
[7]834
835#---------------------------------------------------------------------------------------
836
[591]837class B735(Boeing737CL):
[7]838 """Boeing 737-500 aircraft."""
[8]839 def __init__(self, flight):
840 super(B735, self).__init__(flight)
[797]841 self.dow = 31900
842 self.mtow = 62823
843 self.mlw = 49895
844 self.mzfw = 46720
[611]845 self.maxTakeOffPitch = 14.7
846 self.maxTouchDownPitch = 13.2
[7]847
848#---------------------------------------------------------------------------------------
849
850class DH8D(Aircraft):
851 """Bombardier Dash-8 Q400 aircraft.
852
853 The aircraft type-specific values in the aircraft state have the following
854 structure:
[140]855 - fuel: left, right
[7]856 - n1: left, right
857 - reverser: left, right."""
[140]858
[8]859 def __init__(self, flight):
[591]860 super(DH8D, self).__init__(flight, minLandingFuel = 2000)
[797]861 self.dow = 18508
862 self.mtow = 29574
863 self.mlw = 28123
864 self.mzfw = 26308
[9]865 self.gearSpeedLimit = 215
866 self.flapSpeedLimits = { 5 : 200,
867 10 : 181,
868 15 : 172,
869 35 : 158 }
[611]870 self.maxTakeOffPitch = 8.0
871 self.maxTouchDownPitch = 7.0
[709]872 self.simBriefData = SimBriefData(["I-900", "II-900", "III-900",
873 "I-850", "II-850", "III-850"],
874 ["MCR", "ISC", "LRC", "HSC"],
875 ["I-850", "II-850", "III-850"])
[9]876
[7]877#---------------------------------------------------------------------------------------
878
879class Boeing767(Aircraft):
880 """Base class for the various aircraft in the Boeing 767 family.
881
882 The aircraft type-specific values in the aircraft state have the following
883 structure:
[140]884 - fuel: left, centre, right
[7]885 - n1: left, right
886 - reverser: left, right"""
[140]887
[612]888 def __init__(self, flight, minLandingFuel = 7000):
[591]889 super(Boeing767, self).__init__(flight, minLandingFuel = minLandingFuel)
[9]890 self.gearSpeedLimit = 270
891 self.flapSpeedLimits = { 1 : 255,
892 5 : 235,
893 10 : 215,
894 20 : 215,
895 25 : 185,
896 30 : 175 }
[7]897
[384]898 @property
[512]899 def derateType(self):
900 """Get the derate type for this type."""
901 return DERATE_BOEING
[384]902
[7]903#---------------------------------------------------------------------------------------
904
905class B762(Boeing767):
906 """Boeing 767-200 aircraft."""
[8]907 def __init__(self, flight):
908 super(B762, self).__init__(flight)
[9]909 self.dow = 84507
[797]910 self.mtow = 159210
[9]911 self.mlw = 126098
912 self.mzfw = 114758
[611]913 self.maxTakeOffPitch = 13.1
914 self.maxTouchDownPitch = 11.6
[7]915
916#---------------------------------------------------------------------------------------
917
918class B763(Boeing767):
919 """Boeing 767-300 aircraft."""
[8]920 def __init__(self, flight):
[331]921 super(B763, self).__init__(flight)
[9]922 self.dow = 91311
923 self.mtow = 181436
924 self.mlw = 137892
[797]925 self.mzfw = 114758
[611]926 self.maxTakeOffPitch = 9.6
927 self.maxTouchDownPitch = 8.1
[709]928 self.simBriefData = SimBriefData(["250/290/78"],
929 ["CI", "M76", "M78", "M80", "M82", "M84", "LRC"],
930 ["78/290/250"])
[7]931
[799]932 def setBookedFlight(self, bookedFlight):
933 """Update the aircraft based on the booked flight data (e.g. tail number)."""
934 if bookedFlight.tailNumber=="HA-LHD":
935 self.mtow = 159210
936 self.mlw = 126098
937
[7]938#---------------------------------------------------------------------------------------
939
940class CRJ2(Aircraft):
941 """Bombardier CRJ-200 aircraft.
942
943 The aircraft type-specific values in the aircraft state have the following
944 structure:
[140]945 - fuel: left, centre, right
[7]946 - n1: left, right
947 - reverser: left, right."""
[8]948 def __init__(self, flight):
[591]949 super(CRJ2, self).__init__(flight, minLandingFuel = 1000)
[9]950 self.dow = 14549
951 self.mtow = 22995
952 self.mlw = 21319
953 self.mzfw = 19958
954 self.gearSpeedLimit = 240
955 self.flapSpeedLimits = { 8 : 260,
956 20 : 220,
957 30 : 190,
958 45 : 175 }
[611]959 self.maxTakeOffPitch = 18.0
960 self.maxTouchDownPitch = 18.0
[709]961 self.simBriefData = SimBriefData(["250/70", "290/74"],
962 ["CI", "LRC", "M70", "M72", "M74", "M77", "M80"],
963 ["74/290/250", "77/320/250"])
[7]964
965#---------------------------------------------------------------------------------------
966
967class F70(Aircraft):
968 """Fokker 70 aircraft.
969
970 The aircraft type-specific values in the aircraft state have the following
971 structure:
[140]972 - fuel: left, centre, right
[7]973 - n1: left, right
974 - reverser: left, right."""
[8]975 def __init__(self, flight):
[591]976 super(F70, self).__init__(flight, minLandingFuel = 1900)
[9]977 self.dow = 24283
978 self.mtow = 38100 # FIXME: differentiate by registration number,
979 # MTOW of HA-LMF: 41955
980 self.mlw = 36740
981 self.mzfw = 32655
982 self.gearSpeedLimit = 200
983 self.flapSpeedLimits = { 8 : 250,
984 15 : 220,
985 25 : 220,
986 42 : 180 }
[360]987 self.reverseMinSpeed = 50
[611]988 self.maxTakeOffPitch = 16.0
989 self.maxTouchDownPitch = 16.0
[7]990
[384]991 @property
[512]992 def derateType(self):
993 """Get the derate type for this type."""
994 return DERATE_EPR
[384]995
[7]996#---------------------------------------------------------------------------------------
997
998class DC3(Aircraft):
999 """Lisunov Li-2 (DC-3) aircraft.
1000
1001 The aircraft type-specific values in the aircraft state have the following
1002 structure:
[140]1003 - fuel: left aux, left, right, right aux
[7]1004 - rpm: left, right
1005 - reverser: left, right."""
[8]1006 def __init__(self, flight):
1007 super(DC3, self).__init__(flight)
[9]1008 self.dow = 8627
1009 self.mtow = 11884
1010 self.mlw = 11793
1011 self.mzfw = 11780
1012 self.gearSpeedLimit = 148
1013 self.flapSpeedLimits = { 15 : 135,
1014 30 : 99,
1015 45 : 97 }
[8]1016
1017 def _checkFlightEnd(self, aircraftState):
1018 """Check if the end of the flight has arrived.
1019
1020 This implementation checks the RPM values to be 0."""
1021 for rpm in aircraftState.rpm:
[29]1022 if rpm>0: return False
1023 return True
[7]1024
1025#---------------------------------------------------------------------------------------
1026
1027class T134(Aircraft):
1028 """Tupolev Tu-134 aircraft.
1029
1030 The aircraft type-specific values in the aircraft state have the following
1031 structure:
[140]1032 - fuel: left tip, left aux, centre, right aux, right tip, external 1,
[7]1033 external 2
1034 - n1: left, right
1035 - reverser: left, right."""
[8]1036 def __init__(self, flight):
[591]1037 super(T134, self).__init__(flight, minLandingFuel = 3000)
[210]1038 self.dow = 29500
1039 self.mtow = 49000
[9]1040 self.mlw = 43000
1041 self.mzfw = 38500
1042 self.gearSpeedLimit = 216
[210]1043 self.flapSpeedLimits = { 10 : 450,
1044 20 : 400,
1045 30 : 300 }
[360]1046 self.reverseMinSpeed = 50
[7]1047
[644]1048 self.hasStrobeLight = False
1049
[611]1050 self.maxTakeOffPitch = 16.0
1051 self.maxTouchDownPitch = 16.0
1052
[241]1053 @property
[512]1054 def derateType(self):
1055 """Get the derate type for this type."""
1056 return DERATE_TUPOLEV
[384]1057
1058 @property
[241]1059 def speedInKnots(self):
1060 """Indicate if the speed is in knots."""
1061 return False
[331]1062
[635]1063 @property
1064 def aglInFeet(self):
1065 """Indicate if AGL altituedes are in feet."""
1066 return False
1067
[211]1068 def _appendLightsLoggers(self):
1069 """Append the loggers needed for the lights."""
1070 self._checkers.append(checks.AnticollisionLightsLogger())
1071 self._checkers.append(checks.LandingLightsLogger())
1072 self._checkers.append(checks.NavLightsLogger())
1073
1074 def _appendLightsCheckers(self):
1075 """Append the checkers needed for the lights."""
1076 self._checkers.append(checks.TupolevAntiCollisionLightsChecker())
[631]1077 self._checkers.append(checks.TupolevLandingLightsChecker())
[211]1078 self._checkers.append(checks.LandingLightsChecker())
1079 self._checkers.append(checks.NavLightsChecker())
1080
[7]1081#---------------------------------------------------------------------------------------
1082
1083class T154(Aircraft):
1084 """Tupolev Tu-154 aircraft.
1085
1086 The aircraft type-specific values in the aircraft state have the following
1087 structure:
[140]1088 - fuel: left aux, left, centre, centre 2, right, right aux
[7]1089 - n1: left, centre, right
1090 - reverser: left, right"""
[8]1091 def __init__(self, flight):
[591]1092 super(T154, self).__init__(flight, minLandingFuel = 5000)
[9]1093 self.dow = 53259
1094 self.mtow = 98000
1095 self.mlw = 78000
1096 self.mzfw = 72000
1097 self.gearSpeedLimit = 216
1098 self.flapSpeedLimits = { 15 : 227,
1099 28 : 194,
1100 45 : 162 }
[360]1101 self.reverseMinSpeed = 50
[9]1102
[644]1103 self.hasStrobeLight = False
1104
[611]1105 self.maxTakeOffPitch = 16.0
1106 self.maxTouchDownPitch = 16.0
[709]1107 self.simBriefData = SimBriefData(["AUTO"],
1108 ["300/M80"],
1109 ["AUTO"])
[611]1110
[241]1111 @property
1112 def speedInKnots(self):
1113 """Indicate if the speed is in knots."""
1114 return False
[331]1115
[384]1116 @property
[635]1117 def aglInFeet(self):
1118 """Indicate if AGL altituedes are in feet."""
1119 return False
1120
1121 @property
[512]1122 def derateType(self):
1123 """Get the derate type for this type."""
1124 return DERATE_TUPOLEV
[384]1125
[799]1126 def setBookedFlight(self, bookedFlight):
1127 """Update the aircraft based on the booked flight data (e.g. tail number)."""
1128 if bookedFlight.tailNumber in ["HA-LCM", "HA-LCN", "HA-LCO", "HA-LCP",
1129 "HA-LCR", "HA-LCU", "HA-LCV"]:
1130 self.mtow = 100000
1131 self.mlw = 80000
1132
[211]1133 def _appendLightsLoggers(self):
1134 """Append the loggers needed for the lights."""
1135 self._checkers.append(checks.AnticollisionLightsLogger())
1136 self._checkers.append(checks.LandingLightsLogger())
1137 self._checkers.append(checks.NavLightsLogger())
1138
1139 def _appendLightsCheckers(self):
1140 """Append the checkers needed for the lights."""
1141 self._checkers.append(checks.AntiCollisionLightsChecker())
[631]1142 self._checkers.append(checks.TupolevLandingLightsChecker())
[211]1143 self._checkers.append(checks.LandingLightsChecker())
1144 self._checkers.append(checks.NavLightsChecker())
1145
[539]1146#---------------------------------------------------------------------------------------
1147
1148class YK40(Aircraft):
1149 """Yakovlev Yak-40 aircraft.
1150
1151 The aircraft type-specific values in the aircraft state have the following
1152 structure:
1153 - fuel: left, right
1154 - n1: left, right
1155 - reverser: left, right"""
1156 def __init__(self, flight):
1157 super(YK40, self).__init__(flight)
1158 self.dow = 9400
1159 self.mtow = 17200
1160 self.mlw = 16800
1161 self.mzfw = 12100
1162 self.gearSpeedLimit = 165
1163 self.flapSpeedLimits = { 20 : 165,
1164 35 : 135 }
1165
[644]1166 self.hasStrobeLight = False
1167
[539]1168 @property
1169 def speedInKnots(self):
1170 """Indicate if the speed is in knots."""
1171 return False
1172
1173 @property
[635]1174 def aglInFeet(self):
1175 """Indicate if AGL altituedes are in feet."""
1176 return False
1177
1178 @property
[539]1179 def derateType(self):
1180 """Get the derate type for this type."""
1181 return DERATE_TUPOLEV
1182
1183 def _appendLightsLoggers(self):
1184 """Append the loggers needed for the lights."""
1185 self._checkers.append(checks.AnticollisionLightsLogger())
1186 self._checkers.append(checks.LandingLightsLogger())
1187 self._checkers.append(checks.NavLightsLogger())
1188
1189 def _appendLightsCheckers(self):
1190 """Append the checkers needed for the lights."""
1191 self._checkers.append(checks.AntiCollisionLightsChecker())
1192 self._checkers.append(checks.LandingLightsChecker())
1193 self._checkers.append(checks.NavLightsChecker())
[403]1194
[7]1195#---------------------------------------------------------------------------------------
1196
[443]1197class B462(Aircraft):
1198 """British Aerospace BAe-146 aircraft.
1199
1200 The aircraft type-specific values in the aircraft state have the following
1201 structure:
1202 - fuel: left, centre, right
1203 - n1: left outer, left inner, right inner, right outer
1204 - reverser: empty (the plane has no reversers)"""
1205 def __init__(self, flight):
1206 super(B462, self).__init__(flight)
1207 self.dow = 25706
1208 self.mtow = 43998
1209 self.mlw = 38599
1210 self.mzfw = 33792
1211 self.gearSpeedLimit = 210
1212 self.flapSpeedLimits = { 18 : 217,
1213 24 : 180,
1214 30 : 170,
1215 33 : 150 }
1216
[445]1217 @property
[512]1218 def derateType(self):
1219 """Get the derate type for this type."""
1220 return DERATE_B462
[445]1221
[443]1222#---------------------------------------------------------------------------------------
1223
[274]1224mostFuelTanks = [const.FUELTANK_LEFT_TIP, const.FUELTANK_EXTERNAL1,
1225 const.FUELTANK_LEFT_AUX,
1226 const.FUELTANK_CENTRE,
1227 const.FUELTANK_RIGHT_AUX,
1228 const.FUELTANK_EXTERNAL2, const.FUELTANK_RIGHT_TIP]
[141]1229
1230#---------------------------------------------------------------------------------------
1231
[191]1232_classes = { const.AIRCRAFT_B736 : B736,
1233 const.AIRCRAFT_B737 : B737,
1234 const.AIRCRAFT_B738 : B738,
1235 const.AIRCRAFT_B738C : B738Charter,
[790]1236 const.AIRCRAFT_B732 : B732,
[191]1237 const.AIRCRAFT_B733 : B733,
1238 const.AIRCRAFT_B734 : B734,
1239 const.AIRCRAFT_B735 : B735,
1240 const.AIRCRAFT_DH8D : DH8D,
1241 const.AIRCRAFT_B762 : B762,
1242 const.AIRCRAFT_B763 : B763,
1243 const.AIRCRAFT_CRJ2 : CRJ2,
1244 const.AIRCRAFT_F70 : F70,
1245 const.AIRCRAFT_DC3 : DC3,
1246 const.AIRCRAFT_T134 : T134,
1247 const.AIRCRAFT_T154 : T154,
[443]1248 const.AIRCRAFT_YK40 : YK40,
1249 const.AIRCRAFT_B462 : B462 }
[8]1250
1251#---------------------------------------------------------------------------------------
[197]1252
1253if __name__ == "__main__":
1254 value = SmoothedValue()
1255
1256 print "Adding 1, 12.0"
1257 value.add(1, 12.0)
1258 print value.get()
1259
1260 print "Adding 1, 15.0"
1261 value.add(1, 15.0)
1262 print value.get()
1263
1264 print "Adding 2, 18.0"
1265 value.add(2, 18.0)
1266 print value.get()
1267
1268 print "Adding 2, 20.0"
1269 value.add(2, 20.0)
1270 print value.get()
1271
1272 print "Adding 5, 22.0"
1273 value.add(5, 22.0)
1274 print value.get()
1275
1276 print "Adding 5, 25.0"
1277 value.add(5, 25.0)
1278 print value.get()
1279
1280 print "Adding 5, 29.0"
1281 value.add(5, 29.0)
1282 print value.get()
1283
1284 print "Adding 5, 21.0"
1285 value.add(5, 21.0)
1286 print value.get()
1287
1288 print "Adding 5, 26.0"
1289 value.add(5, 26.0)
1290 print value.get()
1291
1292 print "Adding 2, 30.0"
1293 value.add(2, 30.0)
1294 print value.get()
1295
1296 print "Adding 2, 55.0"
1297 value.add(2, 55.0)
1298 print value.get()
1299
1300#---------------------------------------------------------------------------------------
Note: See TracBrowser for help on using the repository browser.