Changeset 345:a62373a28d90


Ignore:
Timestamp:
12/08/12 15:02:57 (11 years ago)
Author:
István Váradi <ivaradi@…>
Branch:
default
Phase:
public
Message:

Implemented the new, more flexible way of storing the log during flight (#143)

Location:
src/mlx
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • src/mlx/acft.py

    r344 r345  
    259259                                     aircraftState.windSpeed))
    260260                self._logRadios(aircraftState)
    261                 self._logV1R2()
     261                self._logV1R2(aircraftState)
    262262            elif newStage==const.STAGE_DESCENT or newStage==const.STAGE_LANDING:
    263263                self._logRadios(aircraftState)
     
    396396            return str(speed) + " " + self._flight.getEnglishSpeedUnit()
    397397
    398     def _logV1R2(self):
     398    def _logV1R2(self, state = None):
    399399        """Log the V1, Vr and V2 value either newly, or by updating the
    400400        corresponding line."""
     
    405405
    406406        if self._v1r2LineIndex is None:
     407            if state is None:
     408                state = self._aircraftState
    407409            self._v1r2LineIndex = \
    408                 self.logger.message(self._aircraftState.timestamp, message)
     410                self.logger.message(state.timestamp, message)
    409411        else:
    410412            self.logger.updateLine(self._v1r2LineIndex, message)
  • src/mlx/gui/common.py

    r302 r345  
    297297    faultTag.set_property("foreground", "red")
    298298    faultTag.set_property("weight", WEIGHT_BOLD)
    299     buffer.get_tag_table().add(faultTag)   
     299    buffer.get_tag_table().add(faultTag)
    300300
    301301#------------------------------------------------------------------------------
     
    305305
    306306    If isFault is set, use the tag named 'fault'."""
     307    insertTextBuffer(buffer, buffer.get_end_iter(), text, isFault)
     308
     309#------------------------------------------------------------------------------
     310
     311def insertTextBuffer(buffer, iter, text, isFault = False):
     312    """Insert the given line into the given text buffer at the given iterator.
     313
     314    If isFault is set, use the tag named 'fault'."""
    307315    if isFault:
    308         buffer.insert_with_tags_by_name(buffer.get_end_iter(), text,
    309                                         "fault")
     316        buffer.insert_with_tags_by_name(iter, text, "fault")
    310317    else:
    311         buffer.insert(buffer.get_end_iter(), text)
    312 
    313 #------------------------------------------------------------------------------
     318        buffer.insert(iter, text)
     319
     320#------------------------------------------------------------------------------
  • src/mlx/gui/gui.py

    r304 r345  
    9090    def build(self, iconDirectory):
    9191        """Build the GUI."""
    92        
     92
    9393        self._mainWindow = window = gtk.Window()
    9494        window.set_title(WINDOW_TITLE_BASE)
     
    112112        self._notebook = gtk.Notebook()
    113113        mainVBox.pack_start(self._notebook, True, True, 4)
    114        
     114
    115115        self._wizard = Wizard(self)
    116116        label = gtk.Label(xstr("tab_flight"))
     
    131131        label.set_tooltip_text(xstr("tab_weight_help_tooltip"))
    132132        self._notebook.append_page(self._weightHelp, label)
    133        
     133
    134134        (logWidget, self._logView)  = self._buildLogWidget()
    135         addFaultTag(self._logView.get_buffer())       
     135        addFaultTag(self._logView.get_buffer())
    136136        label = gtk.Label(xstr("tab_log"))
    137137        label.set_use_underline(True)
     
    144144        label.set_tooltip_text(xstr("tab_gates_tooltip"))
    145145        self._notebook.append_page(self._fleetGateStatus, label)
    146        
     146
    147147        (self._debugLogWidget, self._debugLogView) = self._buildLogWidget()
    148148        self._debugLogWidget.show_all()
     
    186186        """Get the main window of the GUI."""
    187187        return self._mainWindow
    188        
     188
    189189    @property
    190190    def logger(self):
    191191        """Get the logger used by us."""
    192192        return self._logger
    193        
     193
    194194    @property
    195195    def simulator(self):
    196196        """Get the simulator used by us."""
    197197        return self._simulator
    198        
     198
    199199    @property
    200200    def flight(self):
     
    211211        """Indicate if the user has logged in properly."""
    212212        return self._wizard.loggedIn
    213        
     213
    214214    @property
    215215    def loginResult(self):
     
    251251        """Get Zero-Fuel Weight calculated for the current flight."""
    252252        return self._wizard.zfw
    253        
     253
    254254    @property
    255255    def filedCruiseAltitude(self):
    256256        """Get cruise altitude filed for the current flight."""
    257257        return self._wizard.filedCruiseAltitude
    258        
     258
    259259    @property
    260260    def cruiseAltitude(self):
     
    271271        """Get the METAR of the deprature airport."""
    272272        return self._wizard.departureMETAR
    273        
     273
    274274    @property
    275275    def arrivalMETAR(self):
     
    281281        """Get the name of the departure runway."""
    282282        return self._wizard.departureRunway
    283        
     283
    284284    @property
    285285    def sid(self):
     
    291291        """Get the V1 speed calculated for the flight."""
    292292        return self._wizard.v1
    293        
     293
    294294    @property
    295295    def vr(self):
    296296        """Get the Vr speed calculated for the flight."""
    297297        return self._wizard.vr
    298        
     298
    299299    @property
    300300    def v2(self):
    301301        """Get the V2 speed calculated for the flight."""
    302302        return self._wizard.v2
    303        
     303
    304304    @property
    305305    def arrivalRunway(self):
     
    326326        """Get the Vref speed calculated for the flight."""
    327327        return self._wizard.vref
    328        
     328
    329329    @property
    330330    def flightType(self):
     
    360360                                    self._mainWindow)
    361361            self._updater.start()
    362        
     362
    363363        singleton.raiseCallback = self.raiseCallback
    364364        gtk.main()
     
    398398                                   type = MESSAGETYPE_ERROR,
    399399                                   message_format = xstr("conn_failed"))
    400    
     400
    401401        dialog.set_title(WINDOW_TITLE_BASE)
    402402        dialog.format_secondary_markup(xstr("conn_failed_sec"))
    403        
     403
    404404        dialog.add_button(xstr("button_cancel"), 0)
    405405        dialog.add_button(xstr("button_tryagain"), 1)
    406406        dialog.set_default_response(1)
    407        
     407
    408408        result = dialog.run()
    409409        dialog.hide()
     
    413413        else:
    414414            self.reset()
    415        
     415
    416416    def disconnected(self):
    417417        """Called when we have disconnected from the simulator."""
     
    422422
    423423    def _disconnected(self):
    424         """Called when we have disconnected from the simulator unexpectedly."""       
     424        """Called when we have disconnected from the simulator unexpectedly."""
    425425        self._statusbar.updateConnection(self._connecting, self._connected)
    426426
     
    460460        result = dialog.run()
    461461        dialog.hide()
    462        
     462
    463463        if result==RESPONSETYPE_YES:
    464464            self.reset()
     
    507507
    508508        return True
    509            
    510     def addFlightLogLine(self, timeStr, line, isFault = False):
    511         """Write the given message line to the log."""
    512         gobject.idle_add(self._writeLog,
    513                          formatFlightLogLine(timeStr, line),
    514                          self._logView, isFault)
    515 
    516     def updateFlightLogLine(self, index, timeStr, line):
    517         """Update the line with the given index."""
    518         gobject.idle_add(self._updateFlightLogLine, index,
    519                          formatFlightLogLine(timeStr, line))
    520 
    521     def _updateFlightLogLine(self, index, line):
    522         """Replace the contents of the given line in the log."""
     509
     510    def insertFlightLogLine(self, index, timestampString, text, isFault):
     511        """Insert the flight log line with the given data."""
     512        gobject.idle_add(self._insertFlightLogLine, index,
     513                         formatFlightLogLine(timestampString, text),
     514                         isFault)
     515
     516    def _insertFlightLogLine(self, index, line, isFault):
     517        """Perform the real insertion.
     518
     519        To be called from the event loop."""
     520        buffer = self._logView.get_buffer()
     521        lineIter = buffer.get_iter_at_line(index)
     522        insertTextBuffer(buffer, lineIter, line, isFault = isFault)
     523        self._logView.scroll_mark_onscreen(buffer.get_insert())
     524
     525    def removeFlightLogLine(self, index):
     526        """Remove the flight log line with the given index."""
     527        gobject.idle_add(self._removeFlightLogLine, index)
     528
     529    def _removeFlightLogLine(self, index):
     530        """Perform the real removal."""
    523531        buffer = self._logView.get_buffer()
    524532        startIter = buffer.get_iter_at_line(index)
    525         endIter = buffer.get_iter_at_line(index + 1)
     533        endIter = buffer.get_iter_at_line(index+1)
    526534        buffer.delete(startIter, endIter)
    527         buffer.insert(startIter, line)
    528535        self._logView.scroll_mark_onscreen(buffer.get_insert())
    529536
     
    591598             (event.new_window_state&WINDOW_STATE_ICONIFIED)==0:
    592599            self._mainWindow.present()
    593            
     600
    594601    def raiseCallback(self):
    595602        """Callback for the singleton handling code."""
     
    630637            self._mainWindow.present()
    631638        self._mainWindow.deiconify()
    632            
     639
    633640    def toggleMainWindow(self):
    634641        """Toggle the main window."""
     
    679686        if self._stdioText:
    680687            sys.__stderr__.write(self._stdioText)
    681            
     688
    682689    def writeStdIO(self, text):
    683690        """Write the given text into standard I/O log."""
     
    758765        self._updatePlaneStatus = status
    759766        self._updatePlaneGateNumber = gateNumber
    760        
     767
    761768        self.webHandler.updatePlane(self._updatePlaneResultCallback,
    762769                                    tailNumber, status, gateNumber)
     
    799806            self._stdioText = ""
    800807        if not text: return
    801            
     808
    802809        lines = text.splitlines()
    803810        if text[-1]=="\n":
     
    809816        now = datetime.datetime.now()
    810817        timeStr = "%02d:%02d:%02d: " % (now.hour, now.minute, now.second)
    811            
     818
    812819        for line in lines:
    813820            #print >> sys.__stdout__, line
     
    833840        self._flight.aircraft = acft.Aircraft.create(self._flight)
    834841        self._flight.aircraft._checkers.append(self)
    835        
     842
    836843        if self._simulator is None:
    837844            self._simulator = fs.createSimulator(const.SIM_MSFS9, self)
    838845            fs.setupMessageSending(self.config, self._simulator)
    839846            self._setupTimeSync()
    840        
     847
    841848        self._flight.simulator = self._simulator
    842849
     
    845852
    846853        self._connecting = True
    847         self._simulator.connect(self._flight.aircraft)       
     854        self._simulator.connect(self._flight.aircraft)
    848855
    849856    def startMonitoring(self):
     
    867874        """Build the main menu bar."""
    868875        menuBar = gtk.MenuBar()
    869        
     876
    870877        fileMenuItem = gtk.MenuItem(xstr("menu_file"))
    871878        fileMenu = gtk.Menu()
     
    965972
    966973        helpMenu.append(gtk.SeparatorMenuItem())
    967        
     974
    968975        aboutMenuItem = gtk.ImageMenuItem(gtk.STOCK_ABOUT)
    969976        aboutMenuItem.set_use_stock(True)
     
    982989            label = gtk.Label(xstr("tab_debug_log"))
    983990            label.set_use_underline(True)
    984             label.set_tooltip_text(xstr("tab_debug_log_tooltip"))       
     991            label.set_tooltip_text(xstr("tab_debug_log_tooltip"))
    985992            self._debugLogPage = self._notebook.append_page(self._debugLogWidget, label)
    986993            self._notebook.set_current_page(self._debugLogPage)
     
    10371044            result = dialog.run()
    10381045            dialog.hide()
    1039        
     1046
    10401047        if result==RESPONSETYPE_YES:
    10411048            self._statusIcon.destroy()
     
    10521059        """Callback for editing the checklists."""
    10531060        self._checklistEditor.run()
    1054        
     1061
    10551062    def _editApproachCallouts(self, menuItem):
    10561063        """Callback for editing the approach callouts."""
    10571064        self._approachCalloutsEditor.run()
    1058        
     1065
    10591066    def _editPreferences(self, menuItem):
    10601067        """Callback for editing the preferences."""
     
    10841091            if pirepDirectory is not None:
    10851092                dialog.set_current_folder(pirepDirectory)
    1086        
     1093
    10871094        result = dialog.run()
    10881095        dialog.hide()
     
    11321139                                           parent = self._mainWindow)
    11331140            dialog.set_modal(True)
    1134            
     1141
    11351142
    11361143            filter = gtk.FileFilter()
     
    11381145            filter.add_pattern("*.pirep")
    11391146            dialog.add_filter(filter)
    1140            
     1147
    11411148            filter = gtk.FileFilter()
    11421149            filter.set_name(xstr("file_filter_all"))
     
    11841191        labelAlignment.add(label)
    11851192        table.attach(labelAlignment, 0, 1, 0, 1)
    1186        
     1193
    11871194        label = gtk.Label(bookedFlight.callsign)
    11881195        labelAlignment = gtk.Alignment(xalign = 0.0, yalign = 0.5,
     
    11971204        labelAlignment.add(label)
    11981205        table.attach(labelAlignment, 0, 1, 1, 2)
    1199        
     1206
    12001207        label = gtk.Label(str(bookedFlight.departureTime.date()))
    12011208        labelAlignment = gtk.Alignment(xalign = 0.0, yalign = 0.5,
     
    12101217        labelAlignment.add(label)
    12111218        table.attach(labelAlignment, 0, 1, 2, 3)
    1212        
     1219
    12131220        label = gtk.Label(bookedFlight.departureICAO)
    12141221        labelAlignment = gtk.Alignment(xalign = 0.0, yalign = 0.5,
     
    12231230        labelAlignment.add(label)
    12241231        table.attach(labelAlignment, 0, 1, 3, 4)
    1225        
     1232
    12261233        label = gtk.Label(bookedFlight.arrivalICAO)
    12271234        labelAlignment = gtk.Alignment(xalign = 0.0, yalign = 0.5,
     
    12431250        else:
    12441251            label.set_text("%.1f %%" % (rating,))
    1245        
     1252
    12461253        labelAlignment = gtk.Alignment(xalign = 0.0, yalign = 0.5,
    12471254                                       xscale = 0.0, yscale = 0.0)
     
    12521259        dialog.add_button(xstr("viewPIREP"), 1)
    12531260        dialog.add_button(xstr("sendPIREP"), RESPONSETYPE_OK)
    1254        
     1261
    12551262        return dialog
    1256                            
     1263
    12571264    def sendPIREP(self, pirep, callback = None):
    12581265        """Send the given PIREP."""
     
    12871294            messageFormat = xstr("sendPIREP_failed")
    12881295            secondaryMarkup = xstr("sendPIREP_failed_sec")
    1289        
     1296
    12901297        dialog = gtk.MessageDialog(parent = self._wizard.gui.mainWindow,
    12911298                                   type = type, message_format = messageFormat)
     
    13651372            dialog.set_transient_for(self._mainWindow)
    13661373            dialog.set_modal(True)
    1367            
     1374
    13681375            logoPath = os.path.join(self._programDirectory, "logo.png")
    13691376            logo = pixbuf_new_from_file(logoPath)
    13701377            dialog.set_logo(logo)
    1371                                
     1378
    13721379            dialog.set_program_name(PROGRAM_NAME)
    13731380            dialog.set_version(const.VERSION)
     
    13961403
    13971404    def _showAboutURL(self, dialog, link, user_data):
    1398         """Show the about URL."""       
     1405        """Show the about URL."""
    13991406        webbrowser.open(url = link, new = 1)
  • src/mlx/logger.py

    r315 r345  
    66import sys
    77import time
     8import bisect
    89
    910#--------------------------------------------------------------------------------------
     
    2829
    2930class Logger(object):
    30     """The class with the interface to log the various events."""
     31    """The class with the interface to log the various events.
     32
     33    It contains a list of entries ordered by their timestamps and their ever
     34    increasing IDs."""
     35
     36    class Entry(object):
     37        """An entry in the log."""
     38
     39        # The ID of the next entry to be created
     40        _nextID = 1
     41
     42        def __init__(self, timestamp, text, showTimestamp = True,
     43                     faultID = None, faultScore = 0, id = None):
     44            """Construct the entry."""
     45            if id is None:
     46                self._id = self._nextID
     47                Logger.Entry._nextID += 1
     48            else:
     49                self._id = id
     50
     51            self._timestamp = timestamp
     52            self._text = text
     53            self._showTimestamp = showTimestamp
     54
     55            self._faultID = faultID
     56            self._faultScore = faultScore
     57
     58        @property
     59        def id(self):
     60            """Get the ID of the entry."""
     61            return self._id
     62
     63        @property
     64        def timestamp(self):
     65            """Get the timestamp of this entry."""
     66            return self._timestamp
     67
     68        @property
     69        def timestampString(self):
     70            """Get the timestamp string of this entry.
     71
     72            It returns None, if the timestamp of the entry is not visible."""
     73            return util.getTimestampString(self._timestamp) \
     74                   if self._showTimestamp else None
     75
     76        @property
     77        def text(self):
     78            """Get the text of this entry."""
     79            return self._text
     80
     81        @property
     82        def isFault(self):
     83            """Determine if this is a log entry about a fault."""
     84            return self._faultID is not None
     85
     86        @property
     87        def faultID(self):
     88            """Get the fault ID of the entry.
     89
     90            It may be None, if the entry is not a fault entry."""
     91            return self._faultID
     92
     93        @property
     94        def faultScore(self):
     95            """Get the fault score of the entry, if it is a fault."""
     96            return self._faultScore
     97
     98        def copy(self, text = None):
     99            """Create a copy of this entry with the given values changed."""
     100            return Logger.Entry(self._timestamp,
     101                                self._text if text is None else text,
     102                                showTimestamp = self._showTimestamp,
     103                                faultID = self._faultID,
     104                                faultScore = self._faultScore,
     105                                id = self._id)
     106
     107        def __cmp__(self, other):
     108            """Compare two entries
     109
     110            First their timestamps are compared, and if those are equal, then
     111            their IDs."""
     112            result = cmp(self._timestamp, other.timestamp)
     113            if result==0:
     114                result = cmp(self._id, other._id)
     115            return result
     116
     117    class Fault(object):
     118        """Information about a fault.
     119
     120        It contains the list of log entries that belong to this fault. The list
     121        is ordered so that the first element contains the entry with the
     122        highest score, so that it should be easy to find the actual score."""
     123        def __init__(self, entry):
     124            """Construct the fault info with the given log entry as its only
     125            one."""
     126            self._entries = [entry]
     127
     128        @property
     129        def score(self):
     130            """Get the score of this fault, i.e. the score of the entry with
     131            the highest score."""
     132            return self._entries[0].faultScore if self._entries else 0
     133
     134        def addEntry(self, entry):
     135            """Add an entry to this fault.
     136
     137            The entries will be sorted."""
     138            entries = self._entries
     139            entries.append(entry)
     140            entries.sort(key = Logger.Entry.faultScore, reverse = True)
     141
     142        def removeEntry(self, entry):
     143            """Remove the given entry.
     144
     145            Returns True if at least one entry remains, False otherwise."""
     146            entries = self._entries
     147            for index in range(0, len(entries)):
     148                if entry is entries[index]:
     149                    del entries[index]
     150                    break
     151
     152            return len(entries)>0
     153
    31154    # FIXME: shall we use const.stage2string() instead?
    32155    _stages = { const.STAGE_BOARDING : "Boarding",
     
    42165                const.STAGE_GOAROUND : "Go-Around",
    43166                const.STAGE_END : "End" }
    44    
     167
    45168    NO_GO_SCORE = 10000
    46169
    47170    def __init__(self, output):
    48171        """Construct the logger."""
     172        self._entries = {}
    49173        self._lines = []
     174
    50175        self._faults = {}
    51         self._faultLineIndexes = []
     176
    52177        self._output = output
    53178
     
    55180    def lines(self):
    56181        """Get the lines of the log."""
    57         return self._lines
     182        return [(entry.timestampString, entry.text) for entry in self._lines]
    58183
    59184    @property
    60185    def faultLineIndexes(self):
    61         """Get the array of the indexes of the log line that contains a
    62         fault."""
    63         return self._faultLineIndexes
     186        """Get the sorted array of the indexes of those log lines that contain
     187        a fault."""
     188        faultLineIndexes = []
     189        lines = self._lines
     190        for index in range(0, len(lines)):
     191            if lines[index].isFault:
     192                faultLineIndexes.append(index)
     193        return faultLineIndexes
    64194
    65195    def reset(self):
     
    67197
    68198        The faults logged so far will be cleared."""
     199        self._entries = {}
    69200        self._lines = []
    70         self._faults.clear()
    71         self._faultLineIndexes = []
    72                
    73     def message(self, timestamp, msg, isFault = False):
    74         """Put a simple textual message into the log with the given timestamp."""
    75         timeStr = util.getTimestampString(timestamp)
    76         return self._logLine(msg, timeStr, isFault = isFault)
    77 
    78     def untimedMessage(self, msg, isFault = False):
     201        self._faults = {}
     202
     203    def message(self, timestamp, msg):
     204        """Put a simple textual message into the log with the given timestamp.
     205
     206        Returns an ID of the message so that it could be referred to later."""
     207        return self._addEntry(Logger.Entry(timestamp, msg))
     208
     209    def untimedMessage(self, msg):
    79210        """Put an untimed message into the log."""
    80         return self._logLine(msg, isFault = isFault)
     211        timestamp = self._lines[-1].timestamp if self._lines else 0
     212        return self._addEntry(Logger.Entry(timestamp, msg,
     213                                           showTimestamp = False))
    81214
    82215    def debug(self, msg):
     
    97230                else const.MESSAGETYPE_INFORMATION
    98231            sendMessage(messageType, "Flight stage: " + s, 3)
    99        
     232
    100233    def fault(self, faultID, timestamp, what, score):
    101234        """Report a fault.
     
    104237        this ID has been reported earlier, it will be reported again only if
    105238        the score is greater than last time. This ID can be, e.g. the checker
    106         the report comes from."""
     239        the report comes from.
     240
     241        Returns an ID of the fault, or -1 if it was not logged."""
    107242        if faultID in self._faults:
    108             if score<=self._faults[faultID]:
    109                 return
    110         self._faults[faultID] = score
     243            if score<=self._faults[faultID].score:
     244                return -1
     245
    111246        text = "%s (NO GO)" % (what) if score==Logger.NO_GO_SCORE \
    112247               else "%s (%.1f)" % (what, score)
    113         lineIndex = self.message(timestamp, text, isFault = True)
    114         self._faultLineIndexes.append(lineIndex)
     248
     249        id = self._addEntry(Logger.Entry(timestamp, text, faultID = faultID,
     250                                         faultScore = score))
     251
    115252        (messageType, duration) = (const.MESSAGETYPE_NOGO, 10) \
    116253                                  if score==Logger.NO_GO_SCORE \
    117254                                  else (const.MESSAGETYPE_FAULT, 5)
    118         sendMessage(messageType, text, duration)           
     255        sendMessage(messageType, text, duration)
     256
     257        return id
    119258
    120259    def noGo(self, faultID, timestamp, what):
    121260        """Report a No-Go fault."""
    122         self.fault(faultID, timestamp, what, Logger.NO_GO_SCORE)
     261        return self.fault(faultID, timestamp, what, Logger.NO_GO_SCORE)
    123262
    124263    def getRating(self):
    125264        """Get the rating of the flight so far."""
    126265        totalScore = 100
    127         for (id, score) in self._faults.iteritems():
     266        for fault in self._faults.itervalues():
     267            score = fault.score
    128268            if score==Logger.NO_GO_SCORE:
    129269                return -score
     
    132272        return totalScore
    133273
    134     def updateLine(self, index, line):
    135         """Update the line at the given index with the given string."""
    136         (timeStr, _line) = self._lines[index]
    137         self._lines[index] = (timeStr, line)
    138         self._output.updateFlightLogLine(index, timeStr, line)
    139 
    140     def _logLine(self, line, timeStr = None, isFault = False):
    141         """Log the given line."""
    142         index = len(self._lines)
    143         self._lines.append((timeStr, line))
    144         self._output.addFlightLogLine(timeStr, line, isFault)
    145         return index
    146        
     274    def updateLine(self, id, line):
     275        """Update the line with the given ID with the given string.
     276
     277        Note, that it does not change the status of the line as a fault!"""
     278        self._updateEntry(id, self._entries[id].copy(text = line))
     279
     280    def _addEntry(self, entry):
     281        """Add the given entry to the log.
     282
     283        @return the ID of the new entry."""
     284        assert entry.id not in self._entries
     285
     286        self._entries[entry.id] = entry
     287
     288        if not self._lines or entry>self._lines[-1]:
     289            index = len(self._lines)
     290            self._lines.append(entry)
     291        else:
     292            index = bisect.bisect_left(self._lines, entry)
     293            self._lines.insert(index, entry)
     294
     295        if entry.isFault:
     296            self._addFault(entry)
     297
     298        self._output.insertFlightLogLine(index, entry.timestampString,
     299                                         entry.text, entry.isFault)
     300
     301        return entry.id
     302
     303    def _updateEntry(self, id, newEntry):
     304        """Update the entry with the given ID from the given new entry."""
     305        self._removeEntry(id)
     306        self._addEntry(newEntry)
     307
     308    def _removeEntry(self, id):
     309        """Remove the entry with the given ID."""
     310        assert id in self._entries
     311
     312        entry = self._entries[id]
     313        del self._entries[id]
     314
     315        for index in range(len(self._lines)-1, -1, -1):
     316            if self._lines[index] is entry:
     317                break
     318        del self._lines[index]
     319
     320        if entry.isFault:
     321            faultID = entry.faultID
     322            fault = self._faults[faultID]
     323            if not fault.removeEntry(entry):
     324                del self._faults[faultID]
     325
     326        self._output.removeFlightLogLine(index)
     327
     328    def _addFault(self, entry):
     329        """Add the given fault entry to the fault with the given ID."""
     330        faultID = entry.faultID
     331        if faultID in self._faults:
     332            self._faults[faultID].addEntry(entry)
     333        else:
     334            self._faults[faultID] = Logger.Fault(entry)
     335
    147336#--------------------------------------------------------------------------------------
  • src/mlx/pirep.py

    r303 r345  
    5454            print "Failed loading PIREP from %s: %s" % (path, str(e))
    5555            return None
    56        
     56
    5757    def __init__(self, flight):
    5858        """Initialize the PIREP from the given flight."""
     
    6464        self.cargoWeight = flight.cargoWeight
    6565        self.mailWeight = flight.mailWeight
    66        
     66
    6767        self.filedCruiseAltitude = flight.filedCruiseAltitude
    6868        self.cruiseAltitude = flight.cruiseAltitude
     
    8686        self.flightDefects = flight.flightDefects
    8787        self.delayCodes = flight.delayCodes
    88        
     88
    8989        self.blockTimeStart = flight.blockTimeStart
    9090        self.flightTimeStart = flight.flightTimeStart
     
    9898        self.logLines = logger.lines
    9999        self.faultLineIndexes = logger.faultLineIndexes
    100        
     100
    101101    def getACARSText(self):
    102102        """Get the ACARS text.
     
    121121            if timeStr is not None:
    122122                text += PIREP._formatLine(timeStr, line)
    123                 text += "\n"           
     123                text += "\n"
    124124
    125125        text += "\n[Flight Rating: %.1f]" % (max(0.0, self.rating),)
    126126
    127127        return text
    128    
     128
    129129    def getTimeComment(self):
    130130        """Get the time comment.
Note: See TracChangeset for help on using the changeset viewer.