Beispiel #1
0
    def tod_context_edit_activate_cb(self, menuitem, data=None):
        """Run edit time dialog."""
        #!!!@ require road race specific editor dialog?
        sel = self.view.get_selection().get_selected()
        if sel is not None:
            i = sel[1]  # grab off row iter and read in cur times
            tst = self.riders.get_value(i, COL_TODSTART)
            tft = self.riders.get_value(i, COL_TODFINISH)

            # prepare text entry boxes
            st = ''
            if tst is not None:
                st = tst.timestr()
            ft = ''
            if tft is not None:
                ft = tft.timestr()

            # run the dialog
            (ret, st, ft) = uiutil.edit_times_dlg(self.meet.window, st, ft)
            if ret == 1:
                stod = tod.str2tod(st)
                ftod = tod.str2tod(ft)
                bib = self.riders.get_value(i, COL_BIB)
                series = self.riders.get_value(i, COL_SERIES)
                self.settimes(i, tst=stod, tft=ftod)  # update model
                self.log.info('Race times manually adjusted for rider ' +
                              strops.bibser2bibstr(bib, series))
            else:
                self.log.info('Edit race times cancelled.')
Beispiel #2
0
    def tod_context_edit_activate_cb(self, menuitem, data=None):
        """Run edit time dialog."""
#!!!@ require road race specific editor dialog?
        sel = self.view.get_selection().get_selected()
        if sel is not None:
            i = sel[1]	# grab off row iter and read in cur times
            tst = self.riders.get_value(i, COL_TODSTART)
            tft = self.riders.get_value(i, COL_TODFINISH)

            # prepare text entry boxes
            st = ''
            if tst is not None:
                st = tst.timestr()
            ft = ''
            if tft is not None:
                ft = tft.timestr()

            # run the dialog
            (ret, st, ft) = uiutil.edit_times_dlg(self.meet.window, st, ft)
            if ret == 1:
                stod = tod.str2tod(st)
                ftod = tod.str2tod(ft)
                bib = self.riders.get_value(i, COL_BIB)
                series = self.riders.get_value(i, COL_SERIES)
                self.settimes(i, tst=stod, tft=ftod) # update model
                self.log.info('Race times manually adjusted for rider '
                               + strops.bibser2bibstr(bib, series))
            else:
                self.log.info('Edit race times cancelled.')
Beispiel #3
0
 def menu_timing_recalc(self, entry, ste, fte, nte):
     """Update the net time entry for the supplied start and finish."""
     st = tod.str2tod(ste.get_text())
     ft = tod.str2tod(fte.get_text())
     if st is not None and ft is not None:
         ste.set_text(st.timestr())
         fte.set_text(ft.timestr())
         nte.set_text((ft - st).timestr())
Beispiel #4
0
 def menu_timing_recalc(self, entry, ste, fte, nte):
     """Update the net time entry for the supplied start and finish."""
     st = tod.str2tod(ste.get_text())
     ft = tod.str2tod(fte.get_text())
     if st is not None and ft is not None:
         ste.set_text(st.timestr())
         fte.set_text(ft.timestr())
         nte.set_text((ft - st).timestr())
Beispiel #5
0
    def loadconfig(self):
        """Load race config from disk."""
        self.riders.clear()
        #self.results.clear()

        # defaults
        # +type specific overrides
        cr = ConfigParser.ConfigParser({
            'startlist': '',
            'start': '',
            'lstart': '',
            'places': '',
            'limit': ''
        })
        cr.add_section('race')
        cr.add_section('riders')
        if os.path.isfile(self.configpath):
            self.log.debug('Attempting to read config from ' +
                           repr(self.configpath))
            cr.read(self.configpath)

        # re-load starters/results
        for rs in cr.get('race', 'startlist').split():
            (r, s) = strops.bibstr2bibser(rs)
            self.addrider(r, s)
            if cr.has_option('riders', rs):
                # bbb.sss = comment,inrace,hcap,finish,mbunch
                nr = self.getrider(r, s)
                ril = csv.reader([cr.get('riders', rs)]).next()
                lr = len(ril)
                if lr > 0:
                    nr[COL_COMMENT] = ril[0]
                if lr > 1:
                    nr[COL_INRACE] = strops.confopt_bool(ril[1])
                if lr > 2:
                    nr[COL_HCAP] = tod.str2tod(ril[2])
                if lr > 3:
                    nr[COL_FINISH] = tod.str2tod(ril[3])
                if lr > 4:
                    nr[COL_MBUNCH] = tod.str2tod(ril[4])
                if nr[COL_HCAP] is None:
                    nr[COL_HCAP] = tod.ZERO  # default to 'scratch'
                if self.limit_tod is not None:
                    if nr[COL_HCAP] > self.limit_tod:
                        self.log.error('Handicap greater than limit for ' +
                                       rs + ' set to limit.')
                        nr[COL_HCAP] = self.limit_tod

        places = strops.reformat_bibserplacelist(cr.get('race', 'places'))
        #!!!
        #self.ctrl_places.set_text(places)
        #self.ctrl_places.set_sensitive(False)
        #self.recalculate()

        # re-join an existing timer state
        self.set_start(tod.str2tod(cr.get('race', 'start')),
                       tod.str2tod(cr.get('race', 'lstart')))
Beispiel #6
0
    def loadconfig(self):
        """Load race config from disk."""
        self.riders.clear()
        #self.results.clear()

        # defaults
        # +type specific overrides
        cr = ConfigParser.ConfigParser({'startlist':'',
					'start':'',
                                        'lstart':'',
                                        'places':'',
                                        'limit':''
                                       })
        cr.add_section('race')
        cr.add_section('riders')
        if os.path.isfile(self.configpath):
            self.log.debug('Attempting to read config from '
                               + repr(self.configpath))
            cr.read(self.configpath)

        # re-load starters/results
        for rs in cr.get('race', 'startlist').split():
            (r, s) = strops.bibstr2bibser(rs)
            self.addrider(r, s)
            if cr.has_option('riders', rs):
                # bbb.sss = comment,inrace,hcap,finish,mbunch
                nr = self.getrider(r, s)
                ril = csv.reader([cr.get('riders', rs)]).next()
                lr = len(ril)
                if lr > 0:
                    nr[COL_COMMENT] = ril[0]
                if lr > 1:
                    nr[COL_INRACE] = strops.confopt_bool(ril[1])
                if lr > 2:
                    nr[COL_HCAP] = tod.str2tod(ril[2])
                if lr > 3:
                    nr[COL_FINISH] = tod.str2tod(ril[3])
                if lr > 4:
                    nr[COL_MBUNCH] = tod.str2tod(ril[4])
                if nr[COL_HCAP] is None:
                    nr[COL_HCAP] = tod.ZERO		# default to 'scratch'
                if self.limit_tod is not None:
                    if nr[COL_HCAP] > self.limit_tod:
                        self.log.error('Handicap greater than limit for '
                                        + rs + ' set to limit.')
                        nr[COL_HCAP] = self.limit_tod

        places = strops.reformat_bibserplacelist(cr.get('race', 'places'))
#!!!
        #self.ctrl_places.set_text(places)
        #self.ctrl_places.set_sensitive(False)
        #self.recalculate()

        # re-join an existing timer state
        self.set_start(tod.str2tod(cr.get('race', 'start')),
                       tod.str2tod(cr.get('race', 'lstart')))
Beispiel #7
0
    def loadconfig(self):
        """Load race config from disk."""
        self.riders.clear()
        self.resettimer()
        cr = ConfigParser.ConfigParser({
            'start': '',
            'lstart': '',
            'id': EVENT_ID,
            'finish': '',
            'finished': 'No',
            'startlist': ''
        })
        cr.add_section('event')
        cr.add_section('riders')
        if os.path.isfile(self.configpath):
            self.log.debug('Attempting to read config from path=' +
                           repr(self.configpath))
            cr.read(self.configpath)
        starters = cr.get('event', 'startlist').split()
        # for a sportif - always sort by bib
        starters.sort(cmp=sort_bib)
        for r in starters:
            self.addrider(r)
            if cr.has_option('riders', r):
                nr = self.getrider(r)
                # bib = comment,rftod,rfseen...
                ril = csv.reader([cr.get('riders', r)]).next()
                lr = len(ril)
                if lr > 0:
                    nr[COL_COMMENT] = ril[0]
                if lr > 1:
                    nr[COL_RFTIME] = tod.str2tod(ril[1])
                if lr > 2:
                    for i in range(2, lr):
                        laptod = tod.str2tod(ril[i])
                        if laptod is not None:
                            nr[COL_RFSEEN].append(laptod)
        self.set_start(cr.get('event', 'start'), cr.get('event', 'lstart'))
        self.set_finish(cr.get('event', 'finish'))
        if cr.get('event', 'finished') == 'Yes':
            self.set_finished()

        # After load complete - check config and report. This ensures
        # an error message is left on top of status stack. This is not
        # always a hard fail and the user should be left to determine
        # an appropriate outcome.
        eid = cr.get('event', 'id')
        if eid != EVENT_ID:
            self.log.error('Event configuration mismatch: ' + repr(eid) +
                           ' != ' + repr(EVENT_ID))
Beispiel #8
0
    def loadconfig(self):
        """Load race config from disk."""
        self.riders.clear()
        self.resettimer()
        cr = ConfigParser.ConfigParser({'start':'',
                                        'lstart':'',
                                        'id':EVENT_ID,
                                        'finish':'',
                                        'finished':'No',
                                        'startlist':''})
        cr.add_section('event')
        cr.add_section('riders')
        if os.path.isfile(self.configpath):
            self.log.debug('Attempting to read config from path='
                            + repr(self.configpath))
            cr.read(self.configpath)
        starters = cr.get('event', 'startlist').split()
        # for a sportif - always sort by bib
        starters.sort(cmp=sort_bib)
        for r in starters:
            self.addrider(r)
            if cr.has_option('riders', r):
                nr = self.getrider(r)
                # bib = comment,rftod,rfseen...
                ril = csv.reader([cr.get('riders', r)]).next()
                lr = len(ril)
                if lr > 0:
                    nr[COL_COMMENT] = ril[0]
                if lr > 1:
                    nr[COL_RFTIME] = tod.str2tod(ril[1])
                if lr > 2:
                    for i in range(2, lr):
                        laptod = tod.str2tod(ril[i])
                        if laptod is not None:
                            nr[COL_RFSEEN].append(laptod)
        self.set_start(cr.get('event', 'start'), cr.get('event', 'lstart'))
        self.set_finish(cr.get('event', 'finish'))
        if cr.get('event', 'finished') == 'Yes':
            self.set_finished()

        # After load complete - check config and report. This ensures
        # an error message is left on top of status stack. This is not
        # always a hard fail and the user should be left to determine
        # an appropriate outcome.
        eid = cr.get('event', 'id')
        if eid != EVENT_ID:
            self.log.error('Event configuration mismatch: '
                           + repr(eid) + ' != ' + repr(EVENT_ID))
Beispiel #9
0
    def loadconfig(self):
        """Load race config from disk."""
        self.riders.clear()
        self.results.clear()

        # failsafe defaults -> dual timer, C0 start, PA/PB
        # type specific overrides

        cr = ConfigParser.ConfigParser({
            'startlist': '',
            'start': '',
            'lstart': ''
        })
        cr.add_section('race')
        cr.add_section('riders')
        if os.path.isfile(self.configpath):
            self.log.debug('Attempting to read config from ' +
                           repr(self.configpath))
            cr.read(self.configpath)

        # re-load starters/results
        self.onestart = False
        for rs in cr.get('race', 'startlist').split():
            (r, s) = strops.bibstr2bibser(rs)
            self.addrider(r, s)
            wst = None
            tst = None
            ft = None
            if cr.has_option('riders', rs):
                # bbb.sss = comment,wall_start,timy_start,finish,place
                nr = self.getrider(r, s)
                ril = csv.reader([cr.get('riders', rs)]).next()
                lr = len(ril)
                if lr > 0:
                    nr[COL_COMMENT] = ril[0]
                if lr > 1:
                    wst = tod.str2tod(ril[1])
                if lr > 2:
                    tst = tod.str2tod(ril[2])
                if lr > 3:
                    ft = tod.str2tod(ril[3])
            nri = self.getiter(r, s)
            self.settimes(nri, wst, tst, ft, doplaces=False)
        self.placexfer()

        # re-join any existing timer state -> no, just do a start
        self.set_syncstart(tod.str2tod(cr.get('race', 'start')),
                           tod.str2tod(cr.get('race', 'lstart')))
Beispiel #10
0
 def set_start(self, start='', lstart=None):
     """Set the start time."""
     if type(start) is tod.tod:
         self.start = start
         if lstart is not None:
             self.lstart = lstart
         else:
             self.lstart = self.start
     else:
         self.start = tod.str2tod(start)
         if lstart is not None:
             self.lstart = tod.str2tod(lstart)
         else:
             self.lstart = self.start
     if self.start is not None and self.finish is None:
         self.set_running()
Beispiel #11
0
 def set_start(self, start='', lstart=None):
     """Set the start time."""
     if type(start) is tod.tod:
         self.start = start
         if lstart is not None:
             self.lstart = lstart
         else:
             self.lstart = self.start
     else:
         self.start = tod.str2tod(start)
         if lstart is not None:
             self.lstart = tod.str2tod(lstart)
         else:
             self.lstart = self.start
     if self.start is not None and self.finish is None:
         self.set_running()
Beispiel #12
0
    def loadconfig(self):
        """Load race config from disk."""
        self.riders.clear()
        self.results.clear()

        # failsafe defaults -> dual timer, C0 start, PA/PB
        # type specific overrides

        cr = ConfigParser.ConfigParser({'startlist':'',
					'start':'',
                                        'lstart':''
                                       })
        cr.add_section('race')
        cr.add_section('riders')
        if os.path.isfile(self.configpath):
            self.log.debug('Attempting to read config from '
                               + repr(self.configpath))
            cr.read(self.configpath)

        # re-load starters/results
        self.onestart = False
        for rs in cr.get('race', 'startlist').split():
            (r, s) = strops.bibstr2bibser(rs)
            self.addrider(r, s)
            wst = None
            tst = None
            ft = None
            if cr.has_option('riders', rs):
                # bbb.sss = comment,wall_start,timy_start,finish,place
                nr = self.getrider(r, s)
                ril = csv.reader([cr.get('riders', rs)]).next()
                lr = len(ril)
                if lr > 0:
                    nr[COL_COMMENT] = ril[0]
                if lr > 1:
                    wst = tod.str2tod(ril[1])
                if lr > 2:
                    tst = tod.str2tod(ril[2])
                if lr > 3:
                    ft = tod.str2tod(ril[3])
            nri = self.getiter(r, s)
            self.settimes(nri, wst, tst, ft, doplaces=False)
        self.placexfer()

        # re-join any existing timer state -> no, just do a start
        self.set_syncstart(tod.str2tod(cr.get('race', 'start')),
                           tod.str2tod(cr.get('race', 'lstart')))
Beispiel #13
0
 def set_finish(self, finish=''):
     """Set the finish time."""
     if type(finish) is tod.tod:
         self.finish = finish
     else:
         self.finish = tod.str2tod(finish)
     if self.finish is None:
         if self.start is not None:
             self.set_running()
     else:
         if self.start is None:
             self.set_start('0')
Beispiel #14
0
 def set_finish(self, finish=''):
     """Set the finish time."""
     if type(finish) is tod.tod:
         self.finish = finish
     else:
         self.finish = tod.str2tod(finish)
     if self.finish is None:
         if self.start is not None:
             self.set_running()
     else:
         if self.start is None:
             self.set_start('0')
Beispiel #15
0
 def msg_cb(self, m):
     """Handle message packet in main thread."""
     redraw = False
     if m.header == 'rider':
         self.append_rider(m.text)
     elif m.header == 'time':
         self.elap_lbl.set_text(m.text)
     elif m.header == 'title':
         self.lbl_header.set_text(m.text)
     elif m.header == 'start':
         self.cur_split = tod.str2tod(m.text)
     elif m.erp:
         self.clear()
     return False
Beispiel #16
0
    def append_rider(self, msg):
        sr = msg.split(chr(unt4.US))
        if len(sr) == 5:
            rftime = tod.str2tod(sr[4])
            if rftime is not None:
                if len(self.riders) == 0:
                    # Case 1: Starting a new lap
                    self.cur_lap = (rftime - self.cur_split).truncate(0)
                    self.cur_split = rftime.truncate(0)
                    self.cur_bunchid = 0
                    self.cur_bunchcnt = 1
                    self.last_time = rftime
                    nr = [
                        sr[0],
                        sr[1],
                        sr[2],
                        sr[3],
                        self.cur_lap.rawtime(0),
                        self.cur_bunchcnt,
                        COLOURMAP[self.cur_bunchid][0],
                        rftime,
                    ]
                elif rftime < self.last_time or rftime - self.last_time < tod.tod("1.12"):
                    # Case 2: Same bunch
                    self.last_time = rftime
                    self.cur_bunchcnt += 1
                    nr = [sr[0], sr[1], sr[2], sr[3], "", self.cur_bunchcnt, COLOURMAP[self.cur_bunchid][0], rftime]
                else:
                    # Case 3: New bunch
                    self.riders.append(["", "", "", "", "", "", "#fefefe", None])
                    self.cur_bunchid = (self.cur_bunchid + 1) % COLOURMAPLEN
                    self.cur_bunchcnt = 1
                    self.last_time = rftime
                    nr = [
                        sr[0],
                        sr[1],
                        sr[2],
                        sr[3],
                        "+" + (rftime - self.cur_split).rawtime(0),
                        self.cur_bunchcnt,
                        COLOURMAP[self.cur_bunchid][0],
                        rftime,
                    ]
            else:
                # Informative non-timeline record
                nr = [sr[0], sr[1], sr[2], sr[3], "", "", "#fefefe", None]

            self.riders.append(nr)
            self.map_redraw()  # update src map
            self.map_area.queue_draw()  # queue copy to screen
Beispiel #17
0
 def msg_cb(self, m):
     """Handle message packet in main thread."""
     redraw = False
     if m.header == "rider":
         self.append_rider(m.text)
     elif m.header == "time":
         self.elap_lbl.set_text(m.text)
     elif m.header == "title":
         self.lbl_header.set_text(m.text)
     elif m.header == "start":
         self.cur_split = tod.str2tod(m.text)
     elif m.erp:
         self.clear()
     return False
Beispiel #18
0
 def append_rider(self, msg):
     sr = msg.split(chr(unt4.US))
     if len(sr) == 5:
         rftime = tod.str2tod(sr[4])
         if rftime is not None:
             if len(self.riders) == 0:
                 # Case 1: Starting a new lap
                 self.cur_lap = (rftime-self.cur_split).truncate(0)
                 self.cur_split = rftime.truncate(0)
                 self.cur_bunchid = 0
                 self.cur_bunchcnt = 1
                 self.last_time = rftime
                 nr=[sr[0],sr[1],sr[2],sr[3],
                     self.cur_lap.rawtime(0),
                     self.cur_bunchcnt,
                     COLOURMAP[self.cur_bunchid][0],
                     rftime]
             elif rftime < self.last_time or rftime - self.last_time < tod.tod('1.12'):
                 # Case 2: Same bunch
                 self.last_time = rftime
                 self.cur_bunchcnt += 1
                 nr=[sr[0],sr[1],sr[2],sr[3],
                     '',
                     self.cur_bunchcnt,
                     COLOURMAP[self.cur_bunchid][0],
                     rftime]
             else:
                 # Case 3: New bunch
                 self.riders.append(['','','','','','','#fefefe',None])
                 self.cur_bunchid = (self.cur_bunchid + 1)%COLOURMAPLEN
                 self.cur_bunchcnt = 1
                 self.last_time = rftime
                 nr=[sr[0],sr[1],sr[2],sr[3],
                     '+' + (rftime - self.cur_split).rawtime(0),
                     self.cur_bunchcnt,
                     COLOURMAP[self.cur_bunchid][0],
                     rftime]
         else: 
             # Informative non-timeline record
             nr=[sr[0],sr[1],sr[2],sr[3],
                     '', '', '#fefefe',None]
             
         self.riders.append(nr)
         self.map_redraw()		# update src map
         self.map_area.queue_draw()	# queue copy to screen