Changeset 51:f0f99ac21935
- Timestamp:
- 03/30/12 15:26:43 (13 years ago)
- Branch:
- default
- Phase:
- public
- Location:
- src/mlx
- Files:
-
- 1 added
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
src/mlx/const.py
r36 r51 115 115 #------------------------------------------------------------------------------- 116 116 117 # Plane status: unknown 118 PLANE_UNKNOWN = 0 119 120 # Plane status: at home, i.e. LHBP 121 PLANE_HOME = 1 122 123 # Plane status: away 124 PLANE_AWAY = 2 125 126 # Plane status: parking 127 PLANE_PARKING = 3 128 129 #------------------------------------------------------------------------------- 130 131 # The available gates at LHBP 132 lhbpGateNumbers = [] 133 134 for i in range(1, 7): 135 lhbpGateNumbers.append(str(i)) 136 137 for i in range(10, 19): 138 lhbpGateNumbers.append(str(i)) 139 140 for i in range(24, 28): 141 lhbpGateNumbers.append(str(i)) 142 143 for i in range(31, 39): 144 lhbpGateNumbers.append(str(i)) 145 146 for i in range(42, 47): 147 lhbpGateNumbers.append(str(i)) 148 149 for i in range(60, 84): 150 if i!=70 and i!=80: 151 lhbpGateNumbers.append(str(i)) 152 153 #------------------------------------------------------------------------------- 154 117 155 _stageStrings = { STAGE_BOARDING : "boarding", 118 156 STAGE_PUSHANDTAXI : "pushback and taxi", -
src/mlx/fsuipc.py
r27 r51 17 17 import pyuipc 18 18 else: 19 import pyuipc_ emuas pyuipc19 import pyuipc_sim as pyuipc 20 20 21 21 #------------------------------------------------------------------------------ -
src/mlx/gui/flight.py
r50 r51 2 2 3 3 from mlx.gui.common import * 4 5 import mlx.const as const 6 import mlx.fs as fs 7 from mlx.logger import Logger 8 from mlx.flight import Flight 9 from mlx.acft import Aircraft 4 10 5 11 #----------------------------------------------------------------------------- … … 62 68 self._mainAlignment = gtk.Alignment(xalign = 0.5, yalign = 0.5, 63 69 xscale = 1.0, yscale = 1.0) 64 table.attach(self._mainAlignment, 0, 1, 1, 3) 70 table.attach(self._mainAlignment, 0, 1, 1, 3) 65 71 66 72 buttonAlignment = gtk.Alignment(xalign = 1.0, xscale=0.0, yscale = 0.0) … … 182 188 """Called when the login button was clicked.""" 183 189 self._wizard.gui.beginBusy("Logging in...") 184 self._wizard.gui.webHandler.login(self._ pilotID.get_text(),185 self._p assword.get_text(),186 self._ loginResultCallback)190 self._wizard.gui.webHandler.login(self._loginResultCallback, 191 self._pilotID.get_text(), 192 self._password.get_text()) 187 193 188 194 def _loginResultCallback(self, returned, result): … … 275 281 self._button.set_use_stock(True) 276 282 self._button.set_sensitive(False) 283 self._button.connect("clicked", self._forwardClicked) 277 284 278 285 self._activated = False … … 292 299 self._button.set_sensitive(selection.count_selected_rows()==1) 293 300 301 def _forwardClicked(self, button): 302 """Called when the forward button was clicked.""" 303 selection = self._flightList.get_selection() 304 (listStore, iter) = selection.get_selected() 305 path = listStore.get_path(iter) 306 [index] = path.get_indices() if pygobject else path 307 308 flight = self._wizard.loginResult.flights[index] 309 self._wizard._bookedFlight = flight 310 311 self._updateDepartureGate() 312 313 def _updateDepartureGate(self): 314 """Update the departure gate for the booked flight.""" 315 flight = self._wizard._bookedFlight 316 if flight.departureICAO=="LHBP": 317 self._wizard._getFleet(self._fleetRetrieved) 318 else: 319 self._wizard.jumpPage(2) 320 321 def _fleetRetrieved(self, fleet): 322 """Called when the fleet has been retrieved.""" 323 if fleet is None: 324 self._wizard.jumpPage(2) 325 else: 326 plane = fleet[self._wizard._bookedFlight.tailNumber] 327 if plane is None: 328 self._wizard.jumpPage(2) 329 330 if plane.gateNumber is not None and \ 331 not fleet.isGateConflicting(plane): 332 self._wizard._departureGate = plane.gateNumber 333 self._wizard.jumpPage(2) 334 else: 335 self._wizard.nextPage() 336 337 #----------------------------------------------------------------------------- 338 339 class GateSelectionPage(Page): 340 """Page to select a free gate at LHBP. 341 342 This page should be displayed only if we have fleet information!.""" 343 def __init__(self, wizard): 344 """Construct the gate selection page.""" 345 help = "The airplane's gate position is invalid.\n\n" \ 346 "Select the gate from which you\n" \ 347 "would like to begin the flight." 348 super(GateSelectionPage, self).__init__(wizard, 349 "LHBP gate selection", 350 help) 351 352 self._listStore = gtk.ListStore(str) 353 self._gateList = gtk.TreeView(self._listStore) 354 column = gtk.TreeViewColumn(None, gtk.CellRendererText(), 355 text = 0) 356 column.set_expand(True) 357 self._gateList.append_column(column) 358 self._gateList.set_headers_visible(False) 359 360 gateSelection = self._gateList.get_selection() 361 gateSelection.connect("changed", self._selectionChanged) 362 363 scrolledWindow = gtk.ScrolledWindow() 364 scrolledWindow.add(self._gateList) 365 scrolledWindow.set_size_request(50, -1) 366 scrolledWindow.set_policy(gtk.PolicyType.AUTOMATIC if pygobject 367 else gtk.POLICY_AUTOMATIC, 368 gtk.PolicyType.ALWAYS if pygobject 369 else gtk.POLICY_ALWAYS) 370 371 alignment = gtk.Alignment(xalign = 0.5, yalign = 0.0, xscale = 0.0, yscale = 1.0) 372 alignment.add(scrolledWindow) 373 374 self.setMainWidget(alignment) 375 376 self._button = self.addButton(gtk.STOCK_GO_FORWARD, default = True) 377 self._button.set_use_stock(True) 378 self._button.set_sensitive(False) 379 self._button.connect("clicked", self._forwardClicked) 380 381 def activate(self): 382 """Fill the gate list.""" 383 self._listStore.clear() 384 occupiedGateNumbers = self._wizard._fleet.getOccupiedGateNumbers() 385 for gateNumber in const.lhbpGateNumbers: 386 if gateNumber not in occupiedGateNumbers: 387 self._listStore.append([gateNumber]) 388 389 def _selectionChanged(self, selection): 390 """Called when the selection is changed.""" 391 self._button.set_sensitive(selection.count_selected_rows()==1) 392 393 def _forwardClicked(self, button): 394 """Called when the forward button is clicked.""" 395 selection = self._gateList.get_selection() 396 (listStore, iter) = selection.get_selected() 397 (gateNumber,) = listStore.get(iter, 0) 398 399 self._wizard._departureGate = gateNumber 400 401 self._wizard._updatePlane(self._planeUpdated, 402 self._wizard._bookedFlight.tailNumber, 403 const.PLANE_HOME, 404 gateNumber) 405 406 def _planeUpdated(self, success): 407 """Callback for the plane updating call.""" 408 if success is None or success: 409 self._wizard.nextPage() 410 else: 411 dialog = gtk.MessageDialog(type = MESSAGETYPE_ERROR, 412 buttons = BUTTONSTYPE_OK, 413 message_format = "Gate conflict detected again") 414 dialog.format_secondary_markup("Try to select a different gate.") 415 dialog.run() 416 dialog.hide() 417 418 self._wizard._getFleet(self._fleetRetrieved) 419 420 def _fleetRetrieved(self, fleet): 421 """Called when the fleet has been retrieved.""" 422 if fleet is None: 423 self._wizard.nextPage() 424 else: 425 self.activate() 426 427 #----------------------------------------------------------------------------- 428 429 class ConnectPage(Page): 430 """Page which displays the departure airport and gate (if at LHBP).""" 431 def __init__(self, wizard): 432 """Construct the connect page.""" 433 help = "The flight begins at the airport given below.\n" \ 434 "Park your aircraft there, at the gate below, if given.\n\n" \ 435 "Then press the Connect button to connect to the simulator." 436 super(ConnectPage, self).__init__(wizard, 437 "Connect to the simulator", 438 help) 439 440 alignment = gtk.Alignment(xalign = 0.5, yalign = 0.5, 441 xscale = 0.0, yscale = 0.0) 442 443 table = gtk.Table(2, 2) 444 table.set_row_spacings(4) 445 table.set_col_spacings(16) 446 table.set_homogeneous(True) 447 alignment.add(table) 448 self.setMainWidget(alignment) 449 450 labelAlignment = gtk.Alignment(xalign=1.0, xscale=0.0) 451 label = gtk.Label("ICAO code:") 452 labelAlignment.add(label) 453 table.attach(labelAlignment, 0, 1, 0, 1) 454 455 labelAlignment = gtk.Alignment(xalign=0.0, xscale=0.0) 456 self._departureICAO = gtk.Label() 457 self._departureICAO.set_width_chars(5) 458 self._departureICAO.set_alignment(0.0, 0.5) 459 labelAlignment.add(self._departureICAO) 460 table.attach(labelAlignment, 1, 2, 0, 1) 461 462 labelAlignment = gtk.Alignment(xalign=1.0, xscale=0.0) 463 label = gtk.Label("Gate:") 464 label.set_use_underline(True) 465 labelAlignment.add(label) 466 table.attach(labelAlignment, 0, 1, 1, 2) 467 468 labelAlignment = gtk.Alignment(xalign=0.0, xscale=0.0) 469 self._departureGate = gtk.Label() 470 self._departureGate.set_width_chars(5) 471 self._departureGate.set_alignment(0.0, 0.5) 472 labelAlignment.add(self._departureGate) 473 table.attach(labelAlignment, 1, 2, 1, 2) 474 475 476 self._button = self.addButton("_Connect", default = True) 477 self._button.set_use_underline(True) 478 self._button.connect("clicked", self._connectClicked) 479 480 def activate(self): 481 """Setup the deprature information.""" 482 icao = self._wizard._bookedFlight.departureICAO 483 self._departureICAO.set_markup("<b>" + icao + "</b>") 484 gate = self._wizard._departureGate 485 if gate!="-": 486 gate = "<b>" + gate + "</b>" 487 self._departureGate.set_markup(gate) 488 489 def _connectClicked(self, button): 490 """Called when the Connect button is pressed.""" 491 self._wizard._connectSimulator() 492 294 493 #----------------------------------------------------------------------------- 295 494 … … 307 506 self._pages.append(LoginPage(self)) 308 507 self._pages.append(FlightSelectionPage(self)) 309 508 self._pages.append(GateSelectionPage(self)) 509 self._pages.append(ConnectPage(self)) 510 511 maxWidth = 0 512 maxHeight = 0 513 for page in self._pages: 514 page.show_all() 515 pageSizeRequest = page.size_request() 516 width = pageSizeRequest.width if pygobject else pageSizeRequest[0] 517 height = pageSizeRequest.height if pygobject else pageSizeRequest[1] 518 maxWidth = max(maxWidth, width) 519 maxHeight = max(maxHeight, height) 520 maxWidth += 16 521 maxHeight += 32 522 self.set_size_request(maxWidth, maxHeight) 523 524 self._fleet = None 525 self._fleetCallback = None 526 self._updatePlaneCallback = None 527 310 528 self._loginResult = None 311 529 self._bookedFlight = None 530 self._departureGate = "-" 531 532 self._logger = Logger(output = gui) 533 self._flight = None 534 self._simulator = None 535 312 536 self.setCurrentPage(0) 313 537 314 538 @property 315 539 def loginResult(self): … … 331 555 def nextPage(self): 332 556 """Go to the next page.""" 333 self.setCurrentPage(self._currentPage + 1) 557 self.jumpPage(1) 558 559 def jumpPage(self, count): 560 """Go to the page which is 'count' pages after the current one.""" 561 self.setCurrentPage(self._currentPage + count) 334 562 self.grabDefault() 335 563 … … 337 565 """Make the default button of the current page the default.""" 338 566 self._pages[self._currentPage].grabDefault() 567 568 def _getFleet(self, callback, force = False): 569 """Get the fleet, if needed. 570 571 callback is function that will be called, when the feet is retrieved, 572 or the retrieval fails. It should have a single argument that will 573 receive the fleet object on success, None otherwise. 574 """ 575 if self._fleet is not None and not force: 576 callback(self._fleet) 577 578 self.gui.beginBusy("Retrieving fleet...") 579 self._fleetCallback = callback 580 self.gui.webHandler.getFleet(self._fleetResultCallback) 581 582 def _fleetResultCallback(self, returned, result): 583 """Called when the fleet has been queried.""" 584 gobject.idle_add(self._handleFleetResult, returned, result) 585 586 def _handleFleetResult(self, returned, result): 587 """Handle the fleet result.""" 588 self.gui.endBusy() 589 if returned: 590 self._fleet = result.fleet 591 else: 592 self._fleet = None 593 594 dialog = gtk.MessageDialog(type = MESSAGETYPE_ERROR, 595 buttons = BUTTONSTYPE_OK, 596 message_format = 597 "Failed to retrieve the information on " 598 "the fleet.") 599 dialog.run() 600 dialog.hide() 601 602 self._fleetCallback(self._fleet) 603 604 def _updatePlane(self, callback, tailNumber, status, gateNumber = None): 605 """Update the given plane's gate information.""" 606 self.gui.beginBusy("Updating plane status...") 607 self._updatePlaneCallback = callback 608 self.gui.webHandler.updatePlane(self._updatePlaneResultCallback, 609 tailNumber, status, gateNumber) 610 611 def _updatePlaneResultCallback(self, returned, result): 612 """Callback for the plane updating operation.""" 613 gobject.idle_add(self._handleUpdatePlaneResult, returned, result) 614 615 def _handleUpdatePlaneResult(self, returned, result): 616 """Handle the result of a plane update operation.""" 617 self.gui.endBusy() 618 if returned: 619 success = result.success 620 else: 621 success = None 622 623 dialog = gtk.MessageDialog(type = MESSAGETYPE_ERROR, 624 buttons = BUTTONSTYPE_OK, 625 message_format = 626 "Failed to update the statuis of " 627 "the airplane.") 628 dialog.run() 629 dialog.hide() 630 631 self._updatePlaneCallback(success) 632 633 def _connectSimulator(self): 634 """Connect to the simulator.""" 635 self._logger.reset() 636 self._flight = Flight(self.gui._logger, self.gui) 637 638 self._flight.aircraftType = self._bookedFlight.aircraftType 639 aircraft = self._flight.aircraft = Aircraft.create(self._flight) 640 self._flight.aircraft._checkers.append(self.gui) 641 642 self._flight.cruiseAltitude = -1 643 self._flight.zfw = -1 644 645 if self._simulator is None: 646 self._simulator = fs.createSimulator(const.SIM_MSFS9, self.gui) 647 648 self._flight.simulator = self._simulator 649 self._simulator.connect(aircraft) 650 #self._simulator.startMonitoring() 339 651 340 652 #----------------------------------------------------------------------------- -
src/mlx/gui/gui.py
r50 r51 251 251 def beginBusy(self, message): 252 252 """Begin a period of background processing.""" 253 print dir(self._mainWindow)254 253 self._mainWindow.get_window().set_cursor(self._busyCursor) 255 254 self._statusbar.updateBusyState(message) … … 285 284 self._writeLog(text) 286 285 self._stdioAfterNewLine = False 287 286 288 287 def _connectToggled(self, button): 289 288 """Callback for the connection button.""" -
src/mlx/web.py
r48 r51 7 7 import threading 8 8 import sys 9 import urllib 9 10 import urllib2 10 11 import hashlib … … 102 103 #------------------------------------------------------------------------------ 103 104 105 class Plane(object): 106 """Information about an airplane in the fleet.""" 107 def __init__(self, s): 108 """Build a plane info based on the given string. 109 110 The string consists of three, space-separated fields. 111 The first field is the tail number, the second field is the gate 112 number, the third field is the plane's status as a character.""" 113 try: 114 words = s.split(" ") 115 tailNumber = words[0] 116 self.tailNumber = tailNumber 117 118 status = words[2] if len(words)>2 else None 119 self.status = const.PLANE_HOME if status=="H" else \ 120 const.PLANE_AWAY if status=="A" else \ 121 const.PLANE_PARKING if status=="P" else \ 122 const.PLANE_UNKNOWN 123 124 gateNumber = words[1] if len(words)>1 else "" 125 self.gateNumber = gateNumber if gateNumber else None 126 127 except: 128 print >> sys.stderr, "Plane string is invalid: '" + s + "'" 129 self.tailNumber = None 130 131 def __repr__(self): 132 """Get the representation of the plane object.""" 133 s = "<Plane: %s %s" % (self.tailNumber, 134 "home" if self.status==const.PLANE_HOME else \ 135 "away" if self.status==const.PLANE_AWAY else \ 136 "parking" if self.status==const.PLANE_PARKING \ 137 else "unknown") 138 if self.gateNumber is not None: 139 s += " (gate " + self.gateNumber + ")" 140 s += ">" 141 return s 142 143 144 #------------------------------------------------------------------------------ 145 146 class Fleet(object): 147 """Information about the whole fleet.""" 148 def __init__(self, f): 149 """Construct the fleet information by reading the given file object.""" 150 self._planes = {} 151 while True: 152 line = readline(f) 153 if not line or line == "#END": break 154 155 plane = Plane(line) 156 if plane.tailNumber is not None: 157 self._planes[plane.tailNumber] = plane 158 159 def isGateConflicting(self, plane): 160 """Check if the gate of the given plane conflicts with another plane's 161 position.""" 162 for p in self._planes.itervalues(): 163 if p.tailNumber!=plane.tailNumber and \ 164 p.status==const.PLANE_HOME and \ 165 p.gateNumber==plane.gateNumber: 166 return True 167 168 return False 169 170 def getOccupiedGateNumbers(self): 171 """Get a set containing the numbers of the gates occupied by planes.""" 172 gateNumbers = set() 173 for p in self._planes.itervalues(): 174 if p.status==const.PLANE_HOME and p.gateNumber: 175 gateNumbers.add(p.gateNumber) 176 return gateNumbers 177 178 def __getitem__(self, tailNumber): 179 """Get the plane with the given tail number. 180 181 If the plane is not in the fleet, None is returned.""" 182 return self._planes[tailNumber] if tailNumber in self._planes else None 183 184 def __repr__(self): 185 """Get the representation of the fleet object.""" 186 return self._planes.__repr__() 187 188 #------------------------------------------------------------------------------ 189 104 190 class Result(object): 105 191 """A result object. … … 161 247 iso88592decoder = codecs.getdecoder("iso-8859-2") 162 248 163 def __init__(self, pilotID, password, callback):249 def __init__(self, callback, pilotID, password): 164 250 """Construct the login request with the given pilot ID and 165 251 password.""" … … 205 291 flight2.departureTime)) 206 292 293 f.close() 294 207 295 return result 208 296 297 #------------------------------------------------------------------------------ 298 299 class GetFleet(Request): 300 """Request to get the fleet from the website.""" 301 302 def __init__(self, callback): 303 """Construct the fleet request.""" 304 super(GetFleet, self).__init__(callback) 305 306 def run(self): 307 """Perform the login request.""" 308 url = "http://www.virtualairlines.hu/onlinegates_get.php" 309 310 f = urllib2.urlopen(url) 311 result = Result() 312 result.fleet = Fleet(f) 313 f.close() 314 315 return result 316 317 #------------------------------------------------------------------------------ 318 319 class UpdatePlane(Request): 320 """Update the status of one of the planes in the fleet.""" 321 def __init__(self, callback, tailNumber, status, gateNumber = None): 322 """Construct the request.""" 323 super(UpdatePlane, self).__init__(callback) 324 self._tailNumber = tailNumber 325 self._status = status 326 self._gateNumber = gateNumber 327 328 def run(self): 329 """Perform the plane update.""" 330 url = "http://www.virtualairlines.hu/onlinegates_set.php" 331 332 status = "H" if self._status==const.PLANE_HOME else \ 333 "A" if self._status==const.PLANE_AWAY else \ 334 "P" if self._status==const.PLANE_PARKING else "" 335 336 gateNumber = self._gateNumber if self._gateNumber else "" 337 338 data = urllib.urlencode([("lajstrom", self._tailNumber), 339 ("status", status), 340 ("kapu", gateNumber)]) 341 342 f = urllib2.urlopen(url, data) 343 line = readline(f) 344 345 result = Result() 346 result.success = line == "OK" 347 348 return result 349 209 350 #------------------------------------------------------------------------------ 210 351 … … 223 364 self.daemon = True 224 365 225 def login(self, pilotID, password, callback):366 def login(self, callback, pilotID, password): 226 367 """Enqueue a login request.""" 227 self._addRequest(Login(pilotID, password, callback)) 228 368 self._addRequest(Login(callback, pilotID, password)) 369 370 def getFleet(self, callback): 371 """Enqueue a fleet retrieval request.""" 372 self._addRequest(GetFleet(callback)) 373 374 def updatePlane(self, callback, tailNumber, status, gateNumber = None): 375 """Update the status of the given plane.""" 376 self._addRequest(UpdatePlane(callback, tailNumber, status, gateNumber)) 377 229 378 def run(self): 230 379 """Process the requests.""" … … 255 404 handler.start() 256 405 257 handler.login("P096", "V5fwj", callback) 406 #handler.login(callback, "P096", "V5fwj") 407 #handler.getFleet(callback) 408 # Plane: HA-LEG home (gate 67) 409 handler.updatePlane(callback, "HA-LQC", const.PLANE_AWAY, "72") 258 410 time.sleep(3) 259 260 #------------------------------------------------------------------------------ 411 handler.getFleet(callback) 412 time.sleep(3) 413 414 #------------------------------------------------------------------------------
Note:
See TracChangeset
for help on using the changeset viewer.