Exemplo n.º 1
0
class TimeTrialRecord( wx.Panel ):
	def __init__( self, parent, controller, id = wx.ID_ANY ):
		wx.Panel.__init__(self, parent, id)
		self.SetBackgroundColour( wx.WHITE )

		self.controller = controller

		self.headerNames = [_('Time'), _('Bib')]
		
		self.maxRows = 10
		
		fontSize = 18
		self.font = wx.FontFromPixelSize( wx.Size(0,fontSize), wx.FONTFAMILY_SWISS, wx.NORMAL, wx.FONTWEIGHT_NORMAL )
		self.bigFont = wx.FontFromPixelSize( wx.Size(0,int(fontSize*1.3)), wx.FONTFAMILY_SWISS, wx.NORMAL, wx.FONTWEIGHT_NORMAL )
		self.vbs = wx.BoxSizer(wx.VERTICAL)
		
		tapForTimeLabel = _('Tap for Time')
		if 'WXMAC' in wx.Platform:
			self.recordTimeButton = wx.lib.buttons.ThemedGenButton( self, label=tapForTimeLabel )
			self.recordTimeButton.Bind( wx.EVT_BUTTON, self.doRecordTime )
		else:
			self.recordTimeButton = wx.Button( self, label=tapForTimeLabel )
			self.recordTimeButton.Bind( wx.EVT_LEFT_DOWN, self.doRecordTime )
		
		self.recordTimeButton.SetFont( self.bigFont )
		self.recordTimeButton.SetToolTip(wx.ToolTip(u'\n'.join(
			[_('Tap to Record Times (or press the "t" key).'), _('Then enter the Bib numbers and Save as soon as possible.')]) ))
		
		hbs = wx.BoxSizer( wx.HORIZONTAL )
		hbs.Add( self.recordTimeButton, 0 )
		
		self.grid = ReorderableGrid( self, style = wx.BORDER_SUNKEN )
		self.grid.SetFont( self.font )
		self.grid.EnableReorderRows( False )
		
		dc = wx.WindowDC( self.grid )
		dc.SetFont( self.font )
		width, height = dc.GetTextExtent(" 999 ")
		self.rowLabelSize = width
		self.grid.SetRowLabelSize( self.rowLabelSize )
		
		self.grid.CreateGrid( self.maxRows, len(self.headerNames) )
		self.grid.Bind( gridlib.EVT_GRID_LABEL_LEFT_CLICK, self.doClickLabel )
		for col, name in enumerate(self.headerNames):
			self.grid.SetColLabelValue( col, name )
		self.grid.SetLabelFont( self.font )
		for col in xrange(self.grid.GetNumberCols()):
			attr = gridlib.GridCellAttr()
			attr.SetFont( self.font )
			if col == 0:
				attr.SetEditor( HighPrecisionTimeEditor() )
			elif col == 1:
				attr.SetRenderer( gridlib.GridCellNumberRenderer() )
				attr.SetEditor( gridlib.GridCellNumberEditor() )
			self.grid.SetColAttr( col, attr )
		
		saveLabel = _('Save')
		if 'WXMAC' in wx.Platform:
			self.commitButton = wx.lib.buttons.ThemedGenButton( self, label=saveLabel )
		else:
			self.commitButton = wx.Button( self, label=saveLabel )
		self.commitButton.Bind( wx.EVT_BUTTON, self.doCommit )
		self.commitButton.SetFont( self.bigFont )
		self.commitButton.SetToolTip(wx.ToolTip(_('Save Entries (or press the "s" key)')))
		
		self.vbs.Add( hbs, 0, flag=wx.ALL|wx.EXPAND, border = 4 )
		self.vbs.Add( self.grid, 1, flag=wx.ALL|wx.EXPAND, border = 4 )
		self.vbs.Add( self.commitButton, flag=wx.ALL|wx.ALIGN_RIGHT, border = 4 )
		
		idRecordAcceleratorId, idCommitAccelleratorId = wx.NewId(), wx.NewId()
		self.Bind(wx.EVT_MENU, self.doRecordTime, id=idRecordAcceleratorId)
		self.Bind(wx.EVT_MENU, self.doCommit, id=idCommitAccelleratorId)
		accel_tbl = wx.AcceleratorTable([
			(wx.ACCEL_NORMAL,  ord('T'), idRecordAcceleratorId),
			(wx.ACCEL_NORMAL,  ord('S'), idCommitAccelleratorId),
		])
		self.SetAcceleratorTable(accel_tbl)
		
		self.SetSizer(self.vbs)
		self.Fit()
		
	def doClickLabel( self, event ):
		if event.GetCol() == 0:
			self.doRecordTime( event )
	
	def doRecordTime( self, event ):
		t = Model.race.curRaceTime()
		
		# Trigger the camera.
		with Model.LockRace() as race:
			if not race:
				return
			if race.enableUSBCamera:
				race.photoCount += TakePhoto( 0, StrToSeconds(formatTime(t)) )
	
		# Find the last row without a time.
		self.grid.SetGridCursor( 0, 0, )
		
		emptyRow = self.grid.GetNumberRows() + 1
		success = False
		for i in xrange(2):
			for row in xrange(self.grid.GetNumberRows()):
				if not self.grid.GetCellValue(row, 0):
					emptyRow = row
					break
			if emptyRow >= self.grid.GetNumberRows():
				self.doCommit( event )
			else:
				success = True
				break
		
		if not success:
			Utils.MessageOK( self, u'\n'.join([
                _('Insufficient space to Record Time.'),
                _('Enter Bib numbers and press Commit.'),
                _('Or delete some entries')]), _('Record Time Failed.') )
			return
			
		self.grid.SetCellValue( emptyRow, 0, formatTime(t) )
		
		# Set the edit cursor at the first empty bib position.
		for row in xrange(self.grid.GetNumberRows()):
			text = self.grid.GetCellValue(row, 1)
			if not text or text == '0':
				self.grid.SetGridCursor( row, 1 )
				break
		
	def doCommit( self, event ):
		self.grid.SetGridCursor( 0, 0, )
	
		# Find the last row without a time.
		timesBibs = []
		timesNoBibs = []
		for row in xrange(self.grid.GetNumberRows()):
			tStr = self.grid.GetCellValue(row, 0).strip()
			if not tStr:
				continue
			
			bib = self.grid.GetCellValue(row, 1).strip()
			try:
				bib = int(bib)
			except (TypeError, ValueError):
				bib = 0
			
			if bib:
				timesBibs.append( (tStr, bib) )
			else:
				timesNoBibs.append( tStr )
				
		for row in xrange(self.grid.GetNumberRows()):
			for column in xrange(self.grid.GetNumberCols()):
				self.grid.SetCellValue(row, column, '' )
		
		'''
		for row, tStr in enumerate(timesNoBibs):
			self.grid.SetCellValue( row, 0, tStr )
		'''
			
		self.grid.SetGridCursor( 0, 1 )
			
		if timesBibs and Model.race:
			with Model.LockRace() as race:
				bibRaceSeconds = []
				
				for tStr, bib in timesBibs:
					raceSeconds = StrToSeconds(tStr)
					race.addTime( bib, raceSeconds )
					OutputStreamer.writeNumTime( bib, raceSeconds )
					bibRaceSeconds.append( (bib, raceSeconds) )
				
			wx.CallAfter( Utils.refresh )
			
		self.grid.SetGridCursor( 0, 1 )
	
	def refresh( self ):
		self.grid.AutoSizeRows( False )
		
		dc = wx.WindowDC( self.grid )
		dc.SetFont( self.font )
		
		widthTotal = self.rowLabelSize
		width, height = dc.GetTextExtent(" 00:00:00.000 ")
		self.grid.SetColSize( 0, width )
		widthTotal += width
		
		width, height = dc.GetTextExtent(" 9999 ")
		self.grid.SetColSize( 1, width )
		widthTotal += width
		
		scrollBarWidth = 48
		self.grid.SetSize( (widthTotal + scrollBarWidth, -1) )
		self.GetSizer().SetMinSize( (widthTotal + scrollBarWidth, -1) )
		
		self.grid.ForceRefresh()
		self.Fit()
		
		wx.CallAfter( self.recordTimeButton.SetFocus )
		
	def commit( self ):
		pass
Exemplo n.º 2
0
class TeamResults(wx.Panel):
    #----------------------------------------------------------------------
    def __init__(self, parent):
        """Constructor"""
        wx.Panel.__init__(self, parent)

        self.categoryLabel = wx.StaticText(self, label='Category:')
        self.categoryChoice = wx.Choice(self, choices=['No Categories'])
        self.categoryChoice.SetSelection(0)
        self.categoryChoice.Bind(wx.EVT_CHOICE, self.onCategoryChoice)
        self.statsLabel = wx.StaticText(self, label='   /   ')
        self.refreshButton = wx.Button(self, label='Refresh')
        self.refreshButton.Bind(wx.EVT_BUTTON, self.onRefresh)
        self.publishToHtml = wx.Button(self, label='Publish to Html')
        self.publishToHtml.Bind(wx.EVT_BUTTON, self.onPublishToHtml)
        self.publishToFtp = wx.Button(self, label='Publish to Html with FTP')
        self.publishToFtp.Bind(wx.EVT_BUTTON, self.onPublishToFtp)
        self.publishToExcel = wx.Button(self, label='Publish to Excel')
        self.publishToExcel.Bind(wx.EVT_BUTTON, self.onPublishToExcel)

        self.postPublishCmdLabel = wx.StaticText(self,
                                                 label='Post Publish Cmd:')
        self.postPublishCmd = wx.TextCtrl(self, size=(300, -1))
        self.postPublishExplain = wx.StaticText(
            self,
            label=
            'Command to run after publish.  Use %* for all filenames (eg. "copy %* dirname")'
        )

        hs = wx.BoxSizer(wx.HORIZONTAL)
        hs.Add(self.categoryLabel, flag=wx.TOP, border=4)
        hs.Add(self.categoryChoice)
        hs.AddSpacer(4)
        hs.Add(self.statsLabel, flag=wx.TOP | wx.LEFT | wx.RIGHT, border=4)
        hs.AddStretchSpacer()
        hs.Add(self.refreshButton)
        hs.Add(self.publishToHtml, flag=wx.LEFT, border=48)
        hs.Add(self.publishToFtp, flag=wx.LEFT, border=4)
        hs.Add(self.publishToExcel, flag=wx.LEFT, border=4)

        hs2 = wx.BoxSizer(wx.HORIZONTAL)
        hs2.Add(self.postPublishCmdLabel, flag=wx.ALIGN_CENTRE_VERTICAL)
        hs2.Add(self.postPublishCmd, flag=wx.ALIGN_CENTRE_VERTICAL)
        hs2.Add(self.postPublishExplain,
                flag=wx.ALIGN_CENTRE_VERTICAL | wx.LEFT,
                border=4)

        self.grid = ReorderableGrid(self, style=wx.BORDER_SUNKEN)
        self.grid.DisableDragRowSize()
        self.grid.SetRowLabelSize(64)
        self.grid.CreateGrid(0, len(HeaderNamesTemplate) + 1)
        self.grid.SetRowLabelSize(0)
        self.grid.EnableReorderRows(False)
        self.grid.Bind(wx.grid.EVT_GRID_LABEL_LEFT_CLICK, self.doLabelClick)
        self.grid.Bind(wx.grid.EVT_GRID_CELL_RIGHT_CLICK, self.doCellClick)
        self.sortCol = None

        self.setColNames(getHeaderNames())

        sizer = wx.BoxSizer(wx.VERTICAL)

        sizer.Add(hs, flag=wx.TOP | wx.LEFT | wx.RIGHT, border=4)
        sizer.Add(hs2,
                  flag=wx.ALIGN_RIGHT | wx.TOP | wx.LEFT | wx.RIGHT,
                  border=4)
        sizer.Add(self.grid, 1, flag=wx.EXPAND | wx.TOP | wx.ALL, border=4)
        self.SetSizer(sizer)

    def onRefresh(self, event):
        SeriesModel.model.clearCache()
        self.refresh()

    def onCategoryChoice(self, event):
        wx.CallAfter(self.refresh)

    def readReset(self):
        self.sortCol = None

    def doLabelClick(self, event):
        col = event.GetCol()
        label = self.grid.GetColLabelValue(col)
        if self.sortCol == col:
            self.sortCol = -self.sortCol
        elif self.sortCol == -col:
            self.sortCol = None
        else:
            self.sortCol = col

        if not self.sortCol:
            self.sortCol = None
        wx.CallAfter(self.refresh)

    def doCellClick(self, event):
        if not hasattr(self, 'popupInfo'):
            self.popupInfo = [
                (u'{}...'.format(_('Copy Team to Clipboard')), wx.NewId(),
                 self.onCopyTeam),
            ]
            for p in self.popupInfo:
                if p[2]:
                    self.Bind(wx.EVT_MENU, p[2], id=p[1])

        menu = wx.Menu()
        for i, p in enumerate(self.popupInfo):
            if p[2]:
                menu.Append(p[1], p[0])
            else:
                menu.AppendSeparator()

        self.rowCur, self.colCur = event.GetRow(), event.GetCol()
        self.PopupMenu(menu)
        menu.Destroy()

    def copyCellToClipboard(self, r, c):
        if wx.TheClipboard.Open():
            # Create a wx.TextDataObject
            do = wx.TextDataObject()
            do.SetText(self.grid.GetCellValue(r, c))

            # Add the data to the clipboard
            wx.TheClipboard.SetData(do)
            # Close the clipboard
            wx.TheClipboard.Close()
        else:
            wx.MessageBox(u"Unable to open the clipboard", u"Error")

    def onCopyTeam(self, event):
        self.copyCellToClipboard(self.rowCur, 1)

    def setColNames(self, headerNames):
        for col, headerName in enumerate(headerNames):
            self.grid.SetColLabelValue(col, headerName)
            attr = gridlib.GridCellAttr()
            if headerName in ('Team', ):
                attr.SetAlignment(wx.ALIGN_LEFT, wx.ALIGN_TOP)
            elif headerName in ('Pos', 'Points', 'Gap'):
                attr.SetAlignment(wx.ALIGN_RIGHT, wx.ALIGN_TOP)
            else:
                attr.SetAlignment(wx.ALIGN_CENTRE, wx.ALIGN_TOP)

            attr.SetReadOnly(True)
            self.grid.SetColAttr(col, attr)

    def getGrid(self):
        return self.grid

    def getTitle(self):
        return self.showResults.GetStringSelection() + ' Series Results'

    def fixCategories(self):
        model = SeriesModel.model
        categoryNames = model.getCategoryNamesSortedTeamPublish()
        lastSelection = self.categoryChoice.GetStringSelection()
        self.categoryChoice.SetItems(categoryNames)
        iCurSelection = 0
        for i, n in enumerate(categoryNames):
            if n == lastSelection:
                iCurSelection = i
                break
        self.categoryChoice.SetSelection(iCurSelection)
        self.GetSizer().Layout()

    def refresh(self):
        model = SeriesModel.model
        HeaderNames = getHeaderNames()
        scoreByPoints = model.scoreByPoints
        scoreByTime = model.scoreByTime

        self.postPublishCmd.SetValue(model.postPublishCmd)

        wait = wx.BusyCursor()
        self.raceResults = model.extractAllRaceResults(False)
        del wait

        self.fixCategories()

        categoryName = self.categoryChoice.GetStringSelection()
        if not categoryName or not (scoreByPoints or scoreByTime):
            Utils.AdjustGridSize(self.grid, 0, 0)
            return

        self.grid.ClearGrid()

        pointsForRank = {
            r.getFileName(): r.pointStructure
            for r in model.races
        }

        results, races = GetModelInfo.GetCategoryResultsTeam(
            categoryName,
            self.raceResults,
            pointsForRank,
            useMostEventsCompleted=model.useMostEventsCompleted,
            numPlacesTieBreaker=model.numPlacesTieBreaker,
        )
        results = [rr for rr in results if rr[1] > 0]

        headerNames = HeaderNames + [
            u'{}\n{}'.format(r[1], r[0].strftime('%Y-%m-%d') if r[0] else u'')
            for r in races
        ]

        Utils.AdjustGridSize(self.grid, len(results), len(headerNames))
        self.setColNames(headerNames)

        for row, (team, points, gap, rrs) in enumerate(results):
            self.grid.SetCellValue(row, 0, unicode(row + 1))
            self.grid.SetCellValue(row, 1, unicode(team))
            self.grid.SetCellValue(row, 2, unicode(points))
            self.grid.SetCellValue(row, 3, unicode(gap))
            for q, rt in enumerate(rrs):
                self.grid.SetCellValue(row, 4 + q,
                                       formatTeamResults(scoreByPoints, rt))

            for c in xrange(0, len(headerNames)):
                self.grid.SetCellBackgroundColour(row, c, wx.WHITE)
                self.grid.SetCellTextColour(row, c, wx.BLACK)

        if self.sortCol is not None:

            def getBracketedNumber(v):
                numberMax = 99999
                if not v:
                    return numberMax
                try:
                    return int(reNoDigits.sub('', v.split('(')[1]))
                except (IndexError, ValueError):
                    return numberMax

            data = []
            for r in xrange(0, self.grid.GetNumberRows()):
                rowOrig = [
                    self.grid.GetCellValue(r, c)
                    for c in xrange(0, self.grid.GetNumberCols())
                ]
                rowCmp = rowOrig[:]
                rowCmp[0] = int(rowCmp[0])
                rowCmp[4] = Utils.StrToSeconds(rowCmp[4])
                rowCmp[5:] = [getBracketedNumber(v) for v in rowCmp[5:]]
                rowCmp.extend(rowOrig)
                data.append(rowCmp)

            if self.sortCol > 0:
                fg = wx.WHITE
                bg = wx.Colour(0, 100, 0)
            else:
                fg = wx.BLACK
                bg = wx.Colour(255, 165, 0)

            iCol = abs(self.sortCol)
            data.sort(key=lambda x: x[iCol], reverse=(self.sortCol < 0))
            for r, row in enumerate(data):
                for c, v in enumerate(row[self.grid.GetNumberCols():]):
                    self.grid.SetCellValue(r, c, v)
                    if c == iCol:
                        self.grid.SetCellTextColour(r, c, fg)
                        self.grid.SetCellBackgroundColour(r, c, bg)
                        if c < 4:
                            halign = wx.ALIGN_LEFT
                        elif c == 4 or c == 5:
                            halign = wx.ALIGN_RIGHT
                        else:
                            halign = wx.ALIGN_CENTRE
                        self.grid.SetCellAlignment(r, c, halign, wx.ALIGN_TOP)

        self.statsLabel.SetLabel('{} / {}'.format(
            self.grid.GetNumberRows(),
            GetModelInfo.GetTotalUniqueTeams(self.raceResults)))

        self.grid.AutoSizeColumns(False)
        self.grid.AutoSizeRows(False)

        self.GetSizer().Layout()

    def onPublishToExcel(self, event):
        model = SeriesModel.model

        scoreByPoints = model.scoreByPoints
        scoreByTime = model.scoreByTime
        scoreByPercent = model.scoreByPercent
        scoreByTrueSkill = model.scoreByTrueSkill
        HeaderNames = getHeaderNames()

        if Utils.mainWin:
            if not Utils.mainWin.fileName:
                Utils.MessageOK(self,
                                'You must save your Series to a file first.',
                                'Save Series')
                return

        self.raceResults = model.extractAllRaceResults(False)

        categoryNames = model.getCategoryNamesSortedTeamPublish()
        if not categoryNames:
            return

        pointsForRank = {
            r.getFileName(): r.pointStructure
            for r in model.races
        }

        wb = xlwt.Workbook()

        for categoryName in categoryNames:
            results, races = GetModelInfo.GetCategoryResultsTeam(
                categoryName,
                self.raceResults,
                pointsForRank,
                useMostEventsCompleted=model.useMostEventsCompleted,
                numPlacesTieBreaker=model.numPlacesTieBreaker,
            )
            results = [rr for rr in results if rr[1] > 0]

            headerNames = HeaderNames + [r[1] for r in races]

            ws = wb.add_sheet(re.sub('[:\\/?*\[\]]', ' ', categoryName))
            wsFit = FitSheetWrapper(ws)

            fnt = xlwt.Font()
            fnt.name = 'Arial'
            fnt.bold = True
            fnt.height = int(fnt.height * 1.5)

            headerStyle = xlwt.XFStyle()
            headerStyle.font = fnt

            rowCur = 0
            ws.write_merge(rowCur, rowCur, 0, 8, model.name, headerStyle)
            rowCur += 1
            if model.organizer:
                ws.write_merge(rowCur, rowCur, 0, 8,
                               u'by {}'.format(model.organizer), headerStyle)
                rowCur += 1
            rowCur += 1
            colCur = 0
            ws.write_merge(rowCur, rowCur, colCur, colCur + 4, categoryName,
                           xlwt.easyxf("font: name Arial, bold on;"))

            rowCur += 2
            for c, headerName in enumerate(headerNames):
                wsFit.write(rowCur, c, headerName, labelStyle, bold=True)
            rowCur += 1

            for pos, (team, points, gap, rrs) in enumerate(results):
                wsFit.write(rowCur, 0, pos + 1, numberStyle)
                wsFit.write(rowCur, 1, team, textStyle)
                wsFit.write(rowCur, 2, points, numberStyle)
                wsFit.write(rowCur, 3, gap, numberStyle)
                for q, rt in enumerate(rrs):
                    wsFit.write(rowCur, 4 + q,
                                formatTeamResults(scoreByPoints, rt),
                                centerStyle)
                rowCur += 1

            # Add branding at the bottom of the sheet.
            style = xlwt.XFStyle()
            style.alignment.horz = xlwt.Alignment.HORZ_LEFT
            ws.write(rowCur + 2, 0, brandText, style)

        if Utils.mainWin:
            xlfileName = os.path.splitext(
                Utils.mainWin.fileName)[0] + 'Team.xls'
        else:
            xlfileName = 'ResultsTestTeam.xls'

        try:
            wb.save(xlfileName)
            webbrowser.open(xlfileName, new=2, autoraise=True)
            Utils.MessageOK(
                self, 'Excel file written to:\n\n   {}'.format(xlfileName),
                'Excel Write')
            self.callPostPublishCmd(xlfileName)
        except IOError:
            Utils.MessageOK(
                self,
                'Cannot write "{}".\n\nCheck if this spreadsheet is open.\nIf so, close it, and try again.'
                .format(xlfileName),
                'Excel File Error',
                iconMask=wx.ICON_ERROR)

    def onPublishToHtml(self, event):
        if Utils.mainWin:
            if not Utils.mainWin.fileName:
                Utils.MessageOK(self,
                                'You must save your Series to a file first.',
                                'Save Series')
                return

        htmlfileName = getHtmlFileName()
        model = SeriesModel.model
        model.postPublishCmd = self.postPublishCmd.GetValue().strip()

        try:
            getHtml(htmlfileName)
            webbrowser.open(htmlfileName, new=2, autoraise=True)
            Utils.MessageOK(
                self, u'Html file written to:\n\n   {}'.format(htmlfileName),
                'html Write')
        except IOError:
            Utils.MessageOK(
                self,
                'Cannot write "%s".\n\nCheck if this file is open.\nIf so, close it, and try again.'
                % htmlfileName,
                'Html File Error',
                iconMask=wx.ICON_ERROR)
        self.callPostPublishCmd(htmlfileName)

    def onPublishToFtp(self, event):
        if Utils.mainWin:
            if not Utils.mainWin.fileName:
                Utils.MessageOK(self,
                                'You must save your Series to a file first.',
                                'Save Series')
                return

        htmlfileName = getHtmlFileName()

        try:
            getHtml(htmlfileName)
        except IOError:
            return

        html = io.open(htmlfileName, 'r', encoding='utf-8', newline='').read()
        with FtpWriteFile.FtpPublishDialog(self, html=html) as dlg:
            dlg.ShowModal()
        self.callPostPublishCmd(htmlfileName)

    def commit(self):
        model = SeriesModel.model
        if model.postPublishCmd != self.postPublishCmd.GetValue().strip():
            model.postPublishCmd = self.postPublishCmd.GetValue().strip()
            model.setChanged()

    def callPostPublishCmd(self, fname):
        self.commit()
        postPublishCmd = SeriesModel.model.postPublishCmd
        if postPublishCmd and fname:
            allFiles = [fname]
            if platform.system() == 'Windows':
                files = ' '.join('""{}""'.format(f) for f in allFiles)
            else:
                files = ' '.join('"{}"'.format(f) for f in allFiles)

            if '%*' in postPublishCmd:
                cmd = postPublishCmd.replace('%*', files)
            else:
                cmd = ' '.join([postPublishCmd, files])

            try:
                subprocess.check_call(cmd, shell=True)
            except subprocess.CalledProcessError as e:
                Utils.MessageOK(
                    self,
                    u'{}\n\n    {}\n{}: {}'.format('Post Publish Cmd Error', e,
                                                   'return code',
                                                   e.returncode),
                    _('Post Publish Cmd Error'))
            except Exception as e:
                Utils.MessageOK(
                    self, u'{}\n\n    {}'.format('Post Publish Cmd Error', e),
                    'Post Publish Cmd Error')
Exemplo n.º 3
0
class TeamResults( wx.Panel ):
	def __init__( self, parent, id=wx.ID_ANY, size=wx.DefaultSize ):
		super(TeamResults, self).__init__( parent, id, size=size )
		
		self.state = RaceInputState()
		
		vsOverall = wx.BoxSizer( wx.VERTICAL )
		
		#---------------------------------------------------------------
		self.colnames = (
			_('Pos'),
			_('Team'),
			_('Time'),
			_('Gap'),
		)
		self.grid = ReorderableGrid( self )
		self.grid.CreateGrid( 0, len(self.colnames) )
		self.grid.SetRowLabelSize( 0 )
		self.grid.SetMargins( 0, 0 )
		self.grid.AutoSizeColumns( True )
		self.grid.DisableDragColSize()
		self.grid.DisableDragRowSize()
		
		self.grid.AutoSizeColumns( False )
		self.grid.AutoSizeRows( False )

		#---------------------------------------------------------------
		self.hbs = wx.BoxSizer(wx.HORIZONTAL)
		
		self.categoryLabel = wx.StaticText( self, label = _('Category:') )
		self.categoryChoice = wx.Choice( self )
		self.Bind(wx.EVT_CHOICE, self.doChooseCategory, self.categoryChoice)
		
		self.exportButton = wx.Button( self, label='{} {}/{}'.format(_('Export'), _('Excel'), _('PDF')) )
		self.exportButton.Bind( wx.EVT_BUTTON, self.doExport )
		
		self.hbs.Add( self.categoryLabel, flag=wx.TOP|wx.BOTTOM|wx.LEFT|wx.ALIGN_CENTRE_VERTICAL, border=4 )
		self.hbs.Add( self.categoryChoice, flag=wx.ALL|wx.ALIGN_CENTRE_VERTICAL, border=4 )
		self.hbs.Add( self.exportButton, flag=wx.ALL|wx.ALIGN_CENTRE_VERTICAL, border=4 )
		
		#---------------------------------------------------------------
		
		vsOverall.Add( self.hbs, flag=wx.ALL, border=4 )
		vsOverall.Add( self.grid, 1, flag=wx.EXPAND|wx.ALL, border=4 )
		self.SetSizer( vsOverall )
	
	def doChooseCategory( self, event ):
		Model.setCategoryChoice( self.categoryChoice.GetSelection(), 'resultsCategory' )
		self.refresh()
		
	@logCall
	def doExport( self, event=None ):
		race = Model.race
		if not race:
			return
		
		fileName = Utils.getMainWin().fileName if Utils.getMainWin() else 'Test.cmn'
		
		#---------------------------------------------------------------------------------
		# Create an Excel file.
		#
		xlFileName = os.path.splitext(fileName)[0] + '-TeamResults.xlsx'

		try:
			wb = xlsxwriter.Workbook( xlFileName )
			formats = ExportGrid.ExportGrid.getExcelFormatsXLSX( wb )
			
			ues = Utils.UniqueExcelSheetName()
			for category in race.getCategories( publishOnly=True ):			
				eg = self.toExportGrid( category )
				if eg:
					ws = wb.add_worksheet( ues.getSheetName(category.fullname) )
					eg.toExcelSheetXLSX( formats, ws )
			wb.close()
		except Exception as e:
			logException( e, sys.exc_info() )
		del wb
		
		#---------------------------------------------------------------------------------
		# Create a PDF file.
		#
		pdfFileName = os.path.splitext(fileName)[0] + '-TeamResults.pdf'
		
		try:
			pdf = PDF( orientation = 'P' )
			pdf.set_font( 'Arial', '', 12 )
			pdf.set_author( getpass.getuser() )
			pdf.set_keywords( 'CrossMgr Team Results' )
			pdf.set_creator( Version.AppVerName )
			pdf.set_title( os.path.splitext(pdfFileName)[0].replace('-', ' ') )
			for category in race.getCategories( publishOnly=True ):
				eg = self.toExportGrid( category )
				if eg:
					eg.drawToFitPDF( pdf, orientation=wx.PORTRAIT )
			pdf.output( pdfFileName, 'F' )
		except Exception as e:
			logException( e, sys.exc_info() )
		del pdf
	
	def getColNames( self ):
		race = Model.race
		colnames = list( self.colnames )
		
		col = 2
		if   race.teamRankOption == race.teamRankByRiderTime:
			colnames[col] = u'{}\n{}'.format(_('Time'), Utils.ordinal(race.nthTeamRider))
		elif race.teamRankOption == race.teamRankBySumPoints:
			colnames[col] = u'{}\n{} {}'.format(_('Sum Points'), _('Top'), race.topTeamResults)
		elif race.teamRankOption == race.teamRankBySumTime:
			colnames[col] = u'{}\n{} {}'.format(_('Sum Time'), _('Top'), race.topTeamResults)
		elif race.teamRankOption == race.teamRankBySumPercentTime:
			colnames[col] = u'{}\n{} {}'.format(_('Sum %'), _('Top'), race.topTeamResults)
			
		if race.showNumTeamParticipants:
			colnames.append( _('Participants') )
		return colnames
	
	def updateGrid( self ):
		race = Model.race
		if not race:
			self.grid.ClearGrid()
			return
		category = FixCategories( self.categoryChoice, getattr(race, 'resultsCategory', 0) )
		self.hbs.RecalcSizes()
		self.hbs.Layout()
		for si in self.hbs.GetChildren():
			if si.IsWindow():
				si.GetWindow().Refresh()
		self.category = category
		
		colnames = self.getColNames()
		
		results = GetTeamResults( self.category )
		Utils.AdjustGridSize( self.grid, len(results), len(colnames) )
		
		for col, colName in enumerate(colnames):
			self.grid.SetColLabelValue( col, colName )
			attr = wx.grid.GridCellAttr()
			attr.SetReadOnly( True )
			if col != 1:
				attr.SetAlignment( wx.ALIGN_RIGHT, wx.ALIGN_TOP )			
			self.grid.SetColAttr( col, attr )
		
		for row, r in enumerate(results):
			self.grid.SetCellValue( row, 0, u'{}'.format(row+1) )
			self.grid.SetCellValue( row, 1, r.team )
			self.grid.SetCellValue( row, 2, r.criteria )
			self.grid.SetCellValue( row, 3, r.gap )
			if race.showNumTeamParticipants:
				self.grid.SetCellValue( row, 4, u'{}'.format(r.numParticipants) )
		
		self.grid.AutoSizeColumns( False )
		self.grid.AutoSizeRows( False )
	
	def toExportGrid( self, category ):
		race = Model.race
		if not race:
			self.grid.ClearGrid()
			return None
		
		title = '\n'.join( [race.title, _('Team Results'), category.fullname,] )
		colnames = [c.replace('\n', ' ') for c in self.getColNames()]
		data = [[] for c in colnames]
		for pos, r in enumerate( GetTeamResults(category), 1 ):
			data[0].append( u'{}'.format(pos) )
			data[1].append( r.team )
			data[2].append( r.criteria )
			data[3].append( r.gap )
			if race.showNumTeamParticipants:
				data[4].append( u'{}'.format(r.numParticipants) )
		
		return ExportGrid.ExportGrid( colnames=colnames, data=data, title=title, leftJustifyCols=[1] )
	
	def refresh( self ):
		self.updateGrid()
		
	def commit( self ):
		pass
Exemplo n.º 4
0
class CategorySequence(wx.Panel):
    CategoryCol = 0
    PublishCol = 1
    TeamNCol = 2
    UseNthScoreCol = 3
    TeamPublishCol = 4

    def __init__(self, parent):
        wx.Panel.__init__(self, parent)

        self.alphaSort = wx.Button(self, label=u'Sort Alphabetically')
        self.alphaSort.Bind(wx.EVT_BUTTON, self.onSort)

        self.explanation = wx.StaticText(
            self,
            label=u'\n'.join([
                _("Change the Category order by dragging-and-dropping the first grey column in the table."
                  ),
                _("If 'Use Nth Result Only' is True, 'Team N' specifies the top Nth rider's time to use for the team's time (eg. Team TT, scored on 3rd rider's result)"
                  ),
                _("If 'Use Nth Result Only' if False, 'Team N' specifies the top riders' times to be totaled for the team result (eg. Team Stage Finish, scored on sum of top 3 results for each team)."
                  ),
            ]))

        self.headerNames = [
            'Category', 'Ind. Publish', 'Team N', 'Use Nth Result Only',
            'Team Publish'
        ]

        self.grid = ReorderableGrid(self, style=wx.BORDER_SUNKEN)
        self.grid.DisableDragRowSize()
        self.grid.SetRowLabelSize(64)
        self.grid.CreateGrid(0, len(self.headerNames))
        for col in xrange(self.grid.GetNumberCols()):
            self.grid.SetColLabelValue(col, self.headerNames[col])

        for col in xrange(self.grid.GetNumberCols()):
            attr = gridlib.GridCellAttr()
            if col == self.CategoryCol:
                attr.SetReadOnly(True)
            elif col in (self.PublishCol, self.UseNthScoreCol,
                         self.TeamPublishCol):
                editor = gridlib.GridCellBoolEditor()
                editor.UseStringValues('1', '0')
                attr.SetEditor(editor)
                attr.SetRenderer(gridlib.GridCellBoolRenderer())
                attr.SetAlignment(wx.ALIGN_CENTRE, wx.ALIGN_CENTRE)
            elif col == self.TeamNCol:
                editor = gridlib.GridCellNumberEditor()
                attr.SetEditor(editor)
                attr.SetRenderer(gridlib.GridCellNumberRenderer())
                attr.SetAlignment(wx.ALIGN_CENTRE, wx.ALIGN_CENTRE)

            self.grid.SetColAttr(col, attr)

        self.Bind(gridlib.EVT_GRID_CELL_LEFT_CLICK, self.onGridLeftClick)

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.alphaSort, 0, flag=wx.ALL | wx.ALIGN_RIGHT, border=4)
        sizer.Add(self.explanation, 0, flag=wx.ALL, border=4)
        sizer.Add(self.grid, 1, flag=wx.EXPAND | wx.ALL, border=6)
        self.SetSizer(sizer)

    def onGridLeftClick(self, event):
        if event.GetCol() in (self.PublishCol, self.UseNthScoreCol,
                              self.TeamPublishCol):
            r, c = event.GetRow(), event.GetCol()
            self.grid.SetCellValue(
                r, c, '1' if self.grid.GetCellValue(r, c)[:1] != '1' else '0')
        event.Skip()

    def getGrid(self):
        return self.grid

    def gridAutoSize(self):
        self.grid.AutoSize()
        self.grid.EnableDragGridSize(False)
        self.grid.EnableDragColSize(False)
        self.Layout()
        self.Refresh()

    def refresh(self):
        model = SeriesModel.model
        model.extractAllRaceResults()  # Also harmonizes the categorySequence
        categoryList = model.getCategoriesSorted()

        Utils.AdjustGridSize(self.grid, len(categoryList))
        for row, c in enumerate(categoryList):
            self.grid.SetCellValue(row, self.CategoryCol, c.name)
            self.grid.SetCellValue(row, self.PublishCol, u'01'[int(c.publish)])
            self.grid.SetCellValue(row, self.TeamNCol, unicode(c.teamN))
            self.grid.SetCellValue(row, self.UseNthScoreCol,
                                   u'01'[int(c.useNthScore)])
            self.grid.SetCellValue(row, self.TeamPublishCol,
                                   u'01'[int(c.teamPublish)])
        wx.CallAfter(self.gridAutoSize)

    def getCategoryList(self):
        Category = SeriesModel.Category
        gc = self.grid.GetCellValue
        categories = []
        for row in xrange(self.grid.GetNumberRows()):
            c = Category(name=gc(row, self.CategoryCol),
                         iSequence=row,
                         publish=gc(row, self.PublishCol) == u'1',
                         teamN=max(1, int(gc(row, self.TeamNCol))),
                         useNthScore=gc(row, self.UseNthScoreCol) == u'1',
                         teamPublish=gc(row, self.TeamPublishCol) == u'1')
            categories.append(c)
        return categories

    def commit(self):
        categoryList = self.getCategoryList()
        SeriesModel.model.setCategories(categoryList)

    def onSort(self, event):
        categoryList = self.getCategoryList()
        categoryList.sort(key=operator.attrgetter('name'))
        SeriesModel.model.setCategories(categoryList)
        wx.CallAfter(self.Refresh)
Exemplo n.º 5
0
class Categories(wx.Panel):
    CategoryTypeChoices = [
        _('Start Wave'), u'    ' + _('Component'),
        _('Custom')
    ]
    DistanceTypeChoices = [_('Lap'), _('Race')]

    def __init__(self, parent, id=wx.ID_ANY):
        wx.Panel.__init__(self, parent, id)

        self.state = RaceInputState()

        vs = wx.BoxSizer(wx.VERTICAL)

        self.ignoreColour = wx.Colour(80, 80, 80)
        self.inactiveColour = wx.Colour(220, 220, 220)

        border = 4
        flag = wx.ALL

        hs = wx.BoxSizer(wx.HORIZONTAL)

        self.activateAllButton = wx.Button(self,
                                           label=_('Activate All'),
                                           style=wx.BU_EXACTFIT)
        self.Bind(wx.EVT_BUTTON, self.onActivateAll, self.activateAllButton)
        hs.Add(self.activateAllButton, 0, border=border, flag=flag)

        self.deactivateAllButton = wx.Button(self,
                                             label=_('Deactivate All'),
                                             style=wx.BU_EXACTFIT)
        self.Bind(wx.EVT_BUTTON, self.onDeactivateAll,
                  self.deactivateAllButton)
        hs.Add(self.deactivateAllButton,
               0,
               border=border,
               flag=(flag & ~wx.LEFT))

        hs.AddSpacer(8)

        self.newCategoryButton = wx.Button(self,
                                           label=_('New'),
                                           style=wx.BU_EXACTFIT)
        self.Bind(wx.EVT_BUTTON, self.onNewCategory, self.newCategoryButton)
        hs.Add(self.newCategoryButton, 0, border=border, flag=flag)

        self.delCategoryButton = wx.Button(self,
                                           label=_('Delete'),
                                           style=wx.BU_EXACTFIT)
        self.Bind(wx.EVT_BUTTON, self.onDelCategory, self.delCategoryButton)
        hs.Add(self.delCategoryButton,
               0,
               border=border,
               flag=(flag & ~wx.LEFT))

        hs.AddSpacer(8)

        self.upCategoryButton = wx.Button(self,
                                          label=_('Move') + u' \u2191',
                                          style=wx.BU_EXACTFIT)
        self.Bind(wx.EVT_BUTTON, self.onUpCategory, self.upCategoryButton)
        hs.Add(self.upCategoryButton, 0, border=border, flag=flag)

        self.downCategoryButton = wx.Button(self,
                                            label=_('Move') + u' \u2193',
                                            style=wx.BU_EXACTFIT)
        self.Bind(wx.EVT_BUTTON, self.onDownCategory, self.downCategoryButton)
        hs.Add(self.downCategoryButton,
               0,
               border=border,
               flag=(flag & ~wx.LEFT))

        hs.AddSpacer(8)

        self.addExceptionsButton = wx.Button(self,
                                             label=_('Add Bib Exceptions'),
                                             style=wx.BU_EXACTFIT)
        self.Bind(wx.EVT_BUTTON, self.onAddExceptions,
                  self.addExceptionsButton)
        hs.Add(self.addExceptionsButton, 0, border=border, flag=flag)

        hs.AddSpacer(8)

        self.updateStartWaveNumbersButton = wx.Button(
            self, label=_('Update Start Wave Bibs'), style=wx.BU_EXACTFIT)
        self.Bind(wx.EVT_BUTTON, self.onUpdateStartWaveNumbers,
                  self.updateStartWaveNumbersButton)
        hs.Add(self.updateStartWaveNumbersButton, 0, border=border, flag=flag)

        self.normalizeButton = wx.Button(self,
                                         label=_('Normalize'),
                                         style=wx.BU_EXACTFIT)
        self.Bind(wx.EVT_BUTTON, self.onNormalize, self.normalizeButton)
        hs.Add(self.normalizeButton, 0, border=border, flag=flag)

        hs.AddStretchSpacer()

        self.printButton = wx.Button(self,
                                     label=u'{}...'.format(_('Print')),
                                     style=wx.BU_EXACTFIT)
        self.Bind(wx.EVT_BUTTON, self.onPrint, self.printButton)
        hs.Add(self.printButton, 0, border=border, flag=flag)

        self.grid = ReorderableGrid(self)
        self.colNameFields = [
            (u'', None),
            (_('Category Type'), 'catType'),
            (_('Active'), 'active'),
            (_('Name'), 'name'),
            (_('Gender'), 'gender'),
            (_('Numbers'), 'catStr'),
            (_('Start\nOffset'), 'startOffset'),
            (_('Race\nLaps'), 'numLaps'),
            (_('Race\nMinutes'), 'raceMinutes'),
            (_('Lapped\nRiders\nContinue'), 'lappedRidersMustContinue'),
            (_('Distance'), 'distance'),
            (_('Dist.\nBy'), 'distanceType'),
            (_('First\nLap\nDist.'), 'firstLapDistance'),
            (_('80%\nLap\nTime'), 'rule80Time'),
            (_('CrossMgr\nEstimated\nLaps'), 'suggestedLaps'),
            (_('Publish'), 'publishFlag'),
            (_('Upload'), 'uploadFlag'),
            (_('Series'), 'seriesFlag'),
        ]
        self.computedFields = {'rule80Time', 'suggestedLaps'}
        self.colnames = [
            colName if not colName.startswith('_') else _('Name Copy')
            for colName, fieldName in self.colNameFields
        ]
        self.iCol = {
            fieldName: i
            for i, (colName, fieldName) in enumerate(self.colNameFields)
            if fieldName and not colName.startswith('_')
        }

        self.activeColumn = self.iCol['active']
        self.genderColumn = self.iCol['gender']
        self.numbersColumn = self.iCol['catStr']
        self.grid.CreateGrid(0, len(self.colnames))
        self.grid.SetRowLabelSize(32)
        self.grid.SetMargins(0, 0)
        for col, name in enumerate(self.colnames):
            self.grid.SetColLabelValue(col, name)

        self.cb = None

        self.boolCols = set()
        self.choiceCols = set()
        self.readOnlyCols = set()
        self.dependentCols = set()

        # Set column attributes for the table.
        for col, (colName, fieldName) in enumerate(self.colNameFields):
            attr = gridlib.GridCellAttr()

            if fieldName is None:
                attr.SetRenderer(CategoryIconRenderer())
                attr.SetAlignment(wx.ALIGN_LEFT, wx.ALIGN_CENTRE)
                attr.SetReadOnly(True)
                self.readOnlyCols.add(col)

            elif fieldName == 'catType':
                self.catTypeWidth = 64
                attr.SetEditor(
                    gridlib.GridCellChoiceEditor(self.CategoryTypeChoices,
                                                 False))
                attr.SetAlignment(wx.ALIGN_LEFT, wx.ALIGN_CENTRE)
                self.choiceCols.add(col)

            elif fieldName in {
                    'active', 'lappedRidersMustContinue', 'publishFlag',
                    'uploadFlag', 'seriesFlag'
            }:
                boolEditor = gridlib.GridCellBoolEditor()
                boolEditor.UseStringValues('1', '0')
                attr.SetEditor(boolEditor)
                attr.SetRenderer(gridlib.GridCellBoolRenderer())
                attr.SetAlignment(wx.ALIGN_CENTRE, wx.ALIGN_CENTRE)
                self.boolCols.add(col)
                if fieldName == 'lappedRidersMustContinue':
                    self.dependentCols.add(col)

            elif fieldName == 'gender':
                attr.SetEditor(
                    gridlib.GridCellChoiceEditor(
                        [_('Open'), _('Men'), _('Women')], False))
                self.choiceCols.add(col)

            elif fieldName == 'startOffset':
                attr.SetEditor(TimeEditor())
                attr.SetAlignment(wx.ALIGN_CENTRE, wx.ALIGN_CENTRE)
                self.dependentCols.add(col)

            elif fieldName == 'numLaps':
                attr.SetEditor(wx.grid.GridCellNumberEditor())
                attr.SetAlignment(wx.ALIGN_CENTRE, wx.ALIGN_CENTRE)
                self.dependentCols.add(col)

            elif fieldName == 'raceMinutes':
                attr.SetEditor(wx.grid.GridCellNumberEditor())
                attr.SetAlignment(wx.ALIGN_CENTRE, wx.ALIGN_CENTRE)
                self.dependentCols.add(col)

            elif fieldName in ['rule80Time', 'suggestedLaps']:
                attr.SetReadOnly(True)
                attr.SetAlignment(wx.ALIGN_CENTRE, wx.ALIGN_CENTRE)
                self.readOnlyCols.add(col)
                self.dependentCols.add(col)

            elif fieldName in ['distance', 'firstLapDistance']:
                attr.SetEditor(gridlib.GridCellFloatEditor(7, 3))
                attr.SetRenderer(gridlib.GridCellFloatRenderer(7, 3))
                attr.SetAlignment(wx.ALIGN_CENTRE, wx.ALIGN_CENTRE)
                self.dependentCols.add(col)

            elif fieldName == 'distanceType':
                attr.SetEditor(
                    gridlib.GridCellChoiceEditor(self.DistanceTypeChoices,
                                                 False))
                attr.SetAlignment(wx.ALIGN_RIGHT, wx.ALIGN_CENTRE)
                self.choiceCols.add(col)
                self.dependentCols.add(col)

            elif colName == '_name2':
                attr.SetAlignment(wx.ALIGN_LEFT, wx.ALIGN_CENTRE)
                attr.SetBackgroundColour(wx.Colour(240, 240, 240))
                attr.SetReadOnly(True)

            self.grid.SetColAttr(col, attr)

        self.Bind(gridlib.EVT_GRID_CELL_LEFT_CLICK, self.onGridLeftClick)
        self.Bind(gridlib.EVT_GRID_SELECT_CELL, self.onCellSelected)
        self.Bind(gridlib.EVT_GRID_CELL_CHANGE, self.onCellChanged)
        self.Bind(gridlib.EVT_GRID_EDITOR_CREATED, self.onEditorCreated)

        vs.Add(hs, 0, flag=wx.EXPAND | wx.ALL, border=4)
        vs.Add(self.grid, 1, flag=wx.GROW | wx.ALL | wx.EXPAND)

        self.rowCur = 0
        self.colCur = 0
        self.SetSizer(vs)

    def onPrint(self, event):
        self.commit()
        PrintCategories()

    def onNormalize(self, event):
        self.commit()
        if Model.race:
            Model.race.normalizeCategories()
            self.state.reset()
            self.refresh()

    #------------------------------------------

    def onGridLeftClick(self, event):
        if event.GetCol() in self.boolCols:
            r, c = event.GetRow(), event.GetCol()
            if c == self.iCol['active']:
                active = (self.grid.GetCellValue(r,
                                                 self.iCol['active']) == u'1')
                wx.CallAfter(
                    self.fixRow, r,
                    self.CategoryTypeChoices.index(
                        self.grid.GetCellValue(r, self.iCol['catType'])),
                    not active)
            self.grid.SetCellValue(
                r, c, '1' if self.grid.GetCellValue(r, c)[:1] != '1' else '0')
        event.Skip()

    def onCellSelected(self, event):
        self.rowCur = event.GetRow()
        self.colCur = event.GetCol()
        if self.colCur in self.choiceCols or self.colCur in self.boolCols:
            wx.CallAfter(self.grid.EnableCellEditControl)
        event.Skip()

    def onCellChanged(self, event):
        self.rowCur = event.GetRow()
        self.colCur = event.GetCol()
        if self.colCur in [1, 2]:
            wx.CallAfter(self.fixCells)
        event.Skip()

    def onEditorCreated(self, event):
        if event.GetCol() == self.numbersColumn:
            ctrl = event.GetControl()
            ctrl.Bind(wx.EVT_KEY_DOWN, self.onNumbersKeyEvent)
            ctrl.Bind(wx.EVT_TEXT_PASTE, self.onPaste)
        event.Skip()

    def getCleanClipboardText(self):
        if wx.TheClipboard.Open():
            data = wx.TextDataObject()
            if wx.TheClipboard.GetData(data):
                txt = data.GetText()
                txt = re.sub('[^0-9,-]+', ',', txt)
            wx.TheClipboard.Close()
            return txt
        return None

    def isExternalChange(self):
        if not Model.race:
            return False

        categories = Model.race.getAllCategories()

        for cat in categories:
            try:
                cat.distance = float(cat.distance)
            except:
                cat.distance = None
            try:
                cat.firstLapDistance = float(cat.firstLapDistance)
            except:
                cat.firstLapDistance = None

        if self.grid.GetNumberRows() != len(categories):
            return True

        def distanceMatches(distance, cellValue):
            try:
                value = float(cellValue)
            except ValueError:
                value = None

            if not distance and not value:
                return True
            return u'{:.3f}'.format(distance or 0.0) == cellValue

        def numLapsMatches(numLaps, cellValue):
            v = u'{}'.format(numLaps if numLaps is not None else '')
            return v == cellValue

        return any((
            cat.name != self.grid.GetCellValue(r, self.iCol['name'])
            or cat.catStr != self.grid.GetCellValue(r, self.iCol['catStr'])
            or not distanceMatches(
                cat.distance, self.grid.GetCellValue(r, self.iCol['distance']))
            or not distanceMatches(
                cat.firstLapDistance,
                self.grid.GetCellValue(r, self.iCol['firstLapDistance']))
            or not numLapsMatches(
                cat.numLaps, self.grid.GetCellValue(r, self.iCol['numLaps'])))
                   for r, cat in enumerate(categories))

    def pasteFromClipboard(self, event):
        txt = self.getCleanClipboardText()
        if txt:
            event.GetEventObject().WriteText(txt)
            return True
        return False

    def onNumbersKeyEvent(self, event):
        # Handle column pastes from Excel when there are newlines.
        if event.GetModifiers() == wx.MOD_CONTROL and event.GetKeyCode() == 86:
            if self.pasteFromClipboard(event):
                return
        event.Skip()

    def onPaste(self, event):
        self.pasteFromClipboard(event)
        event.Skip()

    #------------------------------------------

    def onUpdateStartWaveNumbers(self, event):
        self.commit()
        undo.pushState()
        with Model.LockRace() as race:
            race.adjustAllCategoryWaveNumbers()
        self.state.reset()
        wx.CallAfter(self.refresh)
        wx.CallAfter(Utils.refreshForecastHistory)

    def onAddExceptions(self, event):
        with Model.LockRace() as race:
            if not race or not race.getAllCategories():
                return

        r = self.grid.GetGridCursorRow()
        if r is None or r < 0:
            Utils.MessageOK(self, _('You must select a Category first'),
                            _('Select a Category'))
            return

        with Model.LockRace() as race:
            categories = race.getAllCategories()
            category = categories[r]

        dlg = wx.TextEntryDialog(
            self, u'{}: {}'.format(
                category.name,
                _('''Add Bib Exceptions (comma separated).
This will add the given list of Bibs to this category,
and remove them from other categories.'''),
            ), _('Add Bib Exceptions'))
        good = (dlg.ShowModal() == wx.ID_OK)
        if good:
            response = dlg.GetValue()
        dlg.Destroy()
        if not good:
            return

        undo.pushState()
        response = re.sub('[^0-9,]', '', response.replace(' ', ','))
        with Model.LockRace() as race:
            for numException in response.split(','):
                race.addCategoryException(category, numException)

        self.state.reset()
        self.refresh()

    def _setRow(
        self,
        r,
        active,
        name,
        catStr,
        startOffset='00:00:00',
        numLaps=None,
        raceMinutes=None,
        lappedRidersMustContinue=False,
        distance=None,
        distanceType=None,
        firstLapDistance=None,
        gender=None,
        catType=Model.Category.CatWave,
        publishFlag=True,
        uploadFlag=True,
        seriesFlag=True,
    ):

        if len(startOffset) < len('00:00:00'):
            startOffset = '00:' + startOffset

        GetTranslation = _
        gender = gender if gender in ['Men', 'Women'] else 'Open'
        self.grid.SetRowLabelValue(r, u'')
        self.grid.SetCellValue(r, self.iCol['active'],
                               u'1' if active else u'0')
        self.grid.SetCellValue(r, self.iCol['catType'],
                               self.CategoryTypeChoices[catType])
        self.grid.SetCellValue(r, self.iCol['name'], name)
        self.grid.SetCellValue(r, self.iCol['gender'], GetTranslation(gender))
        self.grid.SetCellValue(r, self.iCol['catStr'], catStr)
        self.grid.SetCellValue(r, self.iCol['startOffset'], startOffset)
        self.grid.SetCellValue(r, self.iCol['numLaps'],
                               u'{}'.format(numLaps) if numLaps else u'')
        self.grid.SetCellValue(
            r, self.iCol['raceMinutes'],
            u'{}'.format(raceMinutes) if raceMinutes else u'')
        self.grid.SetCellValue(r, self.iCol['lappedRidersMustContinue'],
                               u'1' if lappedRidersMustContinue else u'0')
        self.grid.SetCellValue(r, self.iCol['rule80Time'], u'')
        self.grid.SetCellValue(r, self.iCol['suggestedLaps'], u'')
        self.grid.SetCellValue(r, self.iCol['distance'],
                               ('%.3f' % distance) if distance else u'')
        self.grid.SetCellValue(
            r, self.iCol['distanceType'],
            self.DistanceTypeChoices[distanceType if distanceType else 0])
        self.grid.SetCellValue(r, self.iCol['firstLapDistance'],
                               ('%.3f' %
                                firstLapDistance) if firstLapDistance else '')
        self.grid.SetCellValue(r, self.iCol['publishFlag'],
                               u'1' if publishFlag else u'0')
        self.grid.SetCellValue(r, self.iCol['uploadFlag'],
                               u'1' if uploadFlag else u'0')
        self.grid.SetCellValue(r, self.iCol['seriesFlag'],
                               u'1' if seriesFlag else u'0')

        race = Model.race
        category = race.categories.get(u'{} ({})'.format(name.strip(), gender),
                                       None) if race else None
        if not category or category.catType != Model.Category.CatWave:
            return

        # Get the 80% time cutoff.
        if not active or not Model.race:
            return

        rule80Time = race.getRule80CountdownTime(category) if race else None
        if rule80Time:
            self.grid.SetCellValue(r, self.iCol['rule80Time'],
                                   Utils.formatTime(rule80Time))

        laps = race.getCategoryRaceLaps().get(category, 0) if race else None
        if laps:
            self.grid.SetCellValue(r, self.iCol['suggestedLaps'],
                                   u'{}'.format(laps))

    def fixRow(self, row, catType, active):
        activeColour = wx.WHITE if active else self.inactiveColour
        colour = activeColour if catType == Model.Category.CatWave else self.ignoreColour
        for colName, fieldName in self.colNameFields:
            if not fieldName:
                continue
            col = self.iCol[fieldName]
            self.grid.SetCellBackgroundColour(
                row, col,
                colour if col in self.dependentCols else activeColour)

    def fixCells(self, event=None):
        for row in xrange(self.grid.GetNumberRows()):
            active = self.grid.GetCellValue(row,
                                            self.iCol['active'])[:1] in 'TtYy1'
            catType = self.CategoryTypeChoices.index(
                self.grid.GetCellValue(row, self.iCol['catType']))
            self.fixRow(row, catType, active)

    def onActivateAll(self, event):
        self.commit()
        if Model.race:
            for c in Model.race.getAllCategories():
                if not c.active:
                    c.active = True
                    Model.race.setChanged()
        self.state.reset()
        wx.CallAfter(self.refresh)

    def onDeactivateAll(self, event):
        self.commit()
        if Model.race:
            for c in Model.race.getAllCategories():
                if c.active:
                    c.active = False
                    Model.race.setChanged()
        self.state.reset()
        wx.CallAfter(self.refresh)

    def doAutosize(self):
        self.grid.AutoSizeColumns(False)
        colWidth = self.grid.GetColSize(self.iCol['catStr'])
        maxWidth = wx.GetDisplaySize().width / 3
        if colWidth > maxWidth:
            self.grid.SetColSize(self.iCol['catStr'], maxWidth)
            self.grid.ForceRefresh()

    def onNewCategory(self, event):
        self.grid.AppendRows(1)
        self._setRow(r=self.grid.GetNumberRows() - 1,
                     active=True,
                     name=u'<{}>     '.format(_('CategoryName')),
                     catStr='100-199,504,-128')
        self.doAutosize()

    def onDelCategory(self, event):
        r = self.grid.GetGridCursorRow()
        if r is None or r < 0:
            return
        if Utils.MessageOKCancel(
                self, u'{} "{} ({})"?'.format(
                    _('Delete Category'),
                    self.grid.GetCellValue(r, 3).strip(),
                    self.grid.GetCellValue(r, 4).strip(),
                ), _('Delete Category')):
            self.grid.DeleteRows(r, 1, True)

    def onUpCategory(self, event):
        self.grid.SaveEditControlValue()
        self.grid.DisableCellEditControl()
        r = self.grid.GetGridCursorRow()
        Utils.SwapGridRows(self.grid, r, r - 1)
        if r - 1 >= 0:
            self.grid.MoveCursorUp(False)
        self.grid.ClearSelection()
        self.grid.SelectRow(max(r - 1, 0), True)

    def onDownCategory(self, event):
        self.grid.SaveEditControlValue()
        self.grid.DisableCellEditControl()
        r = self.grid.GetGridCursorRow()
        Utils.SwapGridRows(self.grid, r, r + 1)
        if r + 1 < self.grid.GetNumberRows():
            self.grid.MoveCursorDown(False)
        self.grid.ClearSelection()
        self.grid.SelectRow(min(r + 1, self.grid.GetNumberRows() - 1), True)

    def refresh(self):
        if not self.isExternalChange() and not self.state.changed():
            return

        # Fix the height of the column labels.
        dc = wx.WindowDC(self.grid)
        dc.SetFont(self.grid.GetLabelFont())
        textHeight = dc.GetTextExtent('Label')[1]
        self.colLabelHeight = textHeight * max(
            name.count('\n') + 1 for name in self.colnames) + textHeight // 4
        self.grid.SetColLabelSize(self.colLabelHeight)

        with Model.LockRace() as race:
            self.grid.ClearGrid()
            if race is None:
                return

            for c in xrange(self.grid.GetNumberCols()):
                if self.grid.GetColLabelValue(c).startswith(_('Distance')):
                    self.grid.SetColLabelValue(
                        c,
                        u'{}\n({})'.format(_('Distance'),
                                           ['km', 'miles'
                                            ][getattr(race, 'distanceUnit',
                                                      0)]))
                    break

            categories = race.getAllCategories()

            if self.grid.GetNumberRows() > 0:
                self.grid.DeleteRows(0, self.grid.GetNumberRows())
            self.grid.AppendRows(len(categories))

            for r, cat in enumerate(categories):
                self._setRow(
                    r=r,
                    active=cat.active,
                    name=cat.name,
                    gender=getattr(cat, 'gender', None),
                    catStr=cat.catStr,
                    catType=cat.catType,
                    startOffset=cat.startOffset,
                    numLaps=cat._numLaps,
                    raceMinutes=cat.raceMinutes,
                    lappedRidersMustContinue=getattr(
                        cat, 'lappedRidersMustContinue', False),
                    distance=getattr(cat, 'distance', None),
                    distanceType=getattr(cat, 'distanceType',
                                         Model.Category.DistanceByLap),
                    firstLapDistance=getattr(cat, 'firstLapDistance', None),
                    publishFlag=cat.publishFlag,
                    uploadFlag=cat.uploadFlag,
                    seriesFlag=cat.seriesFlag,
                )

            self.doAutosize()
            self.fixCells()

            # Force the grid to the correct size.
            self.grid.FitInside()
            self.GetSizer().Layout()

    def commit(self):
        undo.pushState()
        with Model.LockRace() as race:
            self.grid.SaveEditControlValue()
            self.grid.DisableCellEditControl(
            )  # Make sure the current edit is committed.
            if race is None:
                return
            numStrTuples = []
            for r in xrange(self.grid.GetNumberRows()):
                values = {
                    name: self.grid.GetCellValue(r, c)
                    for name, c in self.iCol.iteritems()
                    if name not in self.computedFields
                }
                values['catType'] = self.CategoryTypeChoices.index(
                    values['catType'])
                values['distanceType'] = self.DistanceTypeChoices.index(
                    values['distanceType'])
                numStrTuples.append(values)
            race.setCategories(numStrTuples)
            race.adjustAllCategoryWaveNumbers()
        wx.CallAfter(Utils.refreshForecastHistory)
Exemplo n.º 6
0
	def writeTeamGC():
		headers = (
			['Place', 'Team', 'Gap', 'Combined\nTime'] +
			['{}s'.format(Utils.ordinal(i+1)) for i in xrange(len(model.all_teams))] +
			['Best\nRider GC']
		)
		
		grid = ReorderableGrid( notebook )
		grid.CreateGrid( len(model.team_gc) + len(model.unranked_teams), len(headers) )
		grid.EnableReorderRows( False )
		
		for col, h in enumerate(headers):
			attr = gridlib.GridCellAttr()
			attr.SetReadOnly()
			if h != 'Team':
				attr.SetAlignment( wx.ALIGN_RIGHT, wx.ALIGN_CENTRE )
			grid.SetColAttr( col, attr )
			grid.SetColLabelValue( col, h )
		
		rowNum = 0
		leaderTime = None
		gapLast = None
		timeLast = None
		for place, tgc in enumerate(model.team_gc, 1):
			col = 0
			grid.SetCellValue( rowNum, col, unicode(place) ); col += 1
			grid.SetCellValue( rowNum, col, unicode(tgc[-1]) ); col += 1
			
			combinedTime = tgc[0].value
			if leaderTime is None:
				leaderTime = combinedTime
			gap = combinedTime - leaderTime
			grid.SetCellValue( rowNum, col, Utils.formatTime(gap, twoDigitHours=True) if gap != gapLast else sameGap ); col += 1
			gapLast = gap
			
			grid.SetCellValue( rowNum, col, Utils.formatTime(combinedTime, forceHours=True) if combinedTime != timeLast else sameTime)
			timeLast = combinedTime
			setComment( rowNum, col, formatContextList(tgc[0].context), {'width':512} )
			col += 1
			
			for i in xrange(1, len(tgc)-2):
				if tgc[i].value:
					grid.SetCellValue( rowNum, col, unicode(tgc[i].value) )
					setComment( rowNum, col, u'\n'.join(tgc[i].context), {'width':128} )
				col += 1
			
			grid.SetCellValue( rowNum, col, unicode(tgc[-2].value) )
			setComment( rowNum, col, formatContext(tgc[-2].context), {'width':256} )
			col += 1
			
			rowNum +=1
		
		for team in model.unranked_teams:
			col = 0
			grid.SetCellValue( rowNum, col, 'DNF' ); col += 1
			grid.SetCellValue( rowNum, col, team ); col += 1
			rowNum +=1
	
		grid.GetGridWindow().Bind(wx.EVT_MOTION, getCommentCallback(grid))
		grid.AutoSize()
		return grid
Exemplo n.º 7
0
	def writeIC( stage ):
		ic_fields = ['gap'] + list(Model.IndividualClassification._fields[1:-1])
		riderFields = set( model.registration.getFieldsInUse() )
		headers = (
			['place', 'bib', 'last_name', 'first_name', 'team'] +
			(['uci_id'] if 'uci_id' in riderFields else []) +
			(['license'] if 'license' in riderFields else []) +
			list(ic_fields)
		)
		
		grid = ReorderableGrid( notebook )
		grid.CreateGrid( len(getattr(stage, 'individual_gc', [])), len(headers) )
		grid.EnableReorderRows( False )
		
		for col, h in enumerate(headers):
			attr = gridlib.GridCellAttr()
			attr.SetReadOnly()
			if h in Model.Result.NumericFields or any(t in h for t in ('place', 'time')):
				attr.SetAlignment( wx.ALIGN_RIGHT, wx.ALIGN_CENTRE )
			grid.SetColAttr( col, attr )
			grid.SetColLabelValue( col, Utils.fieldToHeader(h, True) )

		rowNum = 0
		gapLast = None
		timeLast = None
		for place, r in enumerate(stage.individual_gc, 1):
			try:
				rider = model.registration.bibToRider[r.bib]
			except KeyError:
				continue
		
			col = 0
			if r.retired_stage > 0:
				grid.SetCellValue( rowNum, col, u'AB' ); col += 1
			else:
				grid.SetCellValue( rowNum, col, unicode(place) ); col += 1
			
			grid.SetCellValue( rowNum, col, unicode(r.bib) ); col += 1
			grid.SetCellValue( rowNum, col, unicode(rider.last_name).upper()); col += 1
			grid.SetCellValue( rowNum, col, unicode(rider.first_name) ); col += 1
			grid.SetCellValue( rowNum, col, unicode(rider.team) ); col += 1
			
			if 'uci_id' in riderFields:
				grid.SetCellValue( rowNum, col, unicode(rider.uci_id) ); col += 1
			if 'license' in riderFields:
				grid.SetCellValue( rowNum, col, unicode(rider.license) ); col += 1
			
			if r.retired_stage == 0:
				grid.SetCellValue( rowNum, col, Utils.formatTime(r.gap, twoDigitHours=True) if gapLast != r.gap else sameGap )
				gapLast = r.gap
				col += 1
				
				timeCur = r.total_time_with_bonus_plus_penalty
				grid.SetCellValue( rowNum, col, Utils.formatTime(timeCur, twoDigitHours=True) if timeCur != timeLast else sameTime )
				timeLast = timeCur
				col += 1
				
				grid.SetCellValue( rowNum, col, Utils.formatTime(r.total_time_with_bonus_plus_penalty_plus_second_fraction, twoDigitHours=True, extraPrecision=True) ); col += 1
				grid.SetCellValue( rowNum, col, unicode(r.sum_of_places) ); col += 1
				grid.SetCellValue( rowNum, col, unicode(r.last_stage_place) ); col += 1
			
			rowNum +=1
			
		grid.GetGridWindow().Bind(wx.EVT_MOTION, getCommentCallback(grid))
		grid.AutoSize()
		return grid
Exemplo n.º 8
0
class Points(wx.Panel):
	#----------------------------------------------------------------------
	NameCol = 0
	OldNameCol = 1
	DepthCol = 2
	PointsCol = 3
	ParticipationCol = 4
	DNFCol = 5
	
	def __init__(self, parent):
		wx.Panel.__init__(self, parent)

		#--------------------------------------------------------------------------
		box = wx.StaticBox( self, label='Score Competitors and Teams by' )
		bsizer = wx.StaticBoxSizer( box, wx.VERTICAL )
		
		self.scoreByPoints = wx.RadioButton( self, label='Points', style=wx.RB_GROUP )
		self.scoreByPoints.Bind( wx.EVT_RADIOBUTTON, self.fixEnable )
		
		self.scoreByTime = wx.RadioButton( self, label='Time' )
		self.scoreByTime.Bind( wx.EVT_RADIOBUTTON, self.fixEnable )
		
		self.scoreByPercent = wx.RadioButton( self, label='Percent Time (100 * WinnersTime / FinishTime)' )
		self.scoreByPercent.Bind( wx.EVT_RADIOBUTTON, self.fixEnable )
		
		self.scoreByTrueSkill = wx.RadioButton( self, label='TrueSkill' )
		self.scoreByTrueSkill.Bind( wx.EVT_RADIOBUTTON, self.fixEnable )
		
		self.scoreByPoints.SetValue( True )
		
		hb = wx.BoxSizer( wx.HORIZONTAL )
		hb.Add( self.scoreByPoints )
		hb.Add( self.scoreByTime, flag=wx.LEFT, border=16 )
		hb.Add( self.scoreByPercent, flag=wx.LEFT, border=16 )
		hb.Add( self.scoreByTrueSkill, flag=wx.LEFT, border=16 )
		bsizer.Add( hb, flag=wx.ALL, border=2 )
		
		#--------------------------------------------------------------------------
		bsizer.Add( wx.StaticLine(self), 1, flag=wx.EXPAND|wx.ALL, border=4 )
		self.considerPrimePointsOrTimeBonus = wx.CheckBox( self, label='Consider Points or Time Bonuses from CrossMgr Primes' )
		self.considerPrimePointsOrTimeBonus.SetValue( True )
		bsizer.Add( self.considerPrimePointsOrTimeBonus, 0, flag=wx.ALL, border=4 )
		
		#--------------------------------------------------------------------------
		bsizer.Add( wx.StaticLine(self), 1, flag=wx.EXPAND|wx.ALL, border=4 )
		
		maxOptions = 30
		self.considerLabel = wx.StaticText( self, label='{}:'.format('Consider') )
		self.bestResultsToConsider = wx.Choice( self, choices = ['All Results', 'Best Result Only'] + ['{} {} {}'.format('Best', i, 'Results Only') for i in range(2,maxOptions+1)] )
		
		self.participationLabel = wx.StaticText( self, label='{}:'.format('Must have completed') )
		self.mustHaveCompleted = wx.Choice( self, choices = ['{} {}'.format(i, 'or more Events') for i in range(0,maxOptions+1)] )
		
		hb = wx.BoxSizer( wx.HORIZONTAL )
		hb.Add( self.considerLabel, flag=wx.ALIGN_CENTRE_VERTICAL )
		hb.Add( self.bestResultsToConsider )
		hb.Add( self.participationLabel, flag=wx.LEFT|wx.ALIGN_CENTRE_VERTICAL, border=16 )
		hb.Add( self.mustHaveCompleted )
		bsizer.Add( hb, flag=wx.ALL, border=2 )
		
		#--------------------------------------------------------------------------
		bsizer.Add( wx.StaticLine(self), 1, flag=wx.EXPAND|wx.ALL, border=4 )
		self.ifRidersTiedOnPoints = wx.StaticText(self, label='If Riders are Tied on Points:')
		bsizer.Add( self.ifRidersTiedOnPoints, flag=wx.ALL, border=2 )
		self.mostEventsCompleted = wx.CheckBox( self, label='Consider Number of Events Completed' )
		self.mostEventsCompleted.SetValue( False )
		bsizer.Add( self.mostEventsCompleted, 0, flag=wx.ALL, border=4 )
		
		bsizer.Add( wx.StaticLine(self), 1, flag=wx.EXPAND|wx.ALL, border=4 )
		self.numPlacesTieBreaker = wx.RadioBox(self, majorDimension=3, style=wx.RA_SPECIFY_ROWS, choices = [
			'Do not consider Place Finishes.',
			'Number of 1st Place Finishes',
			'Number of 1st then 2nd Place Finishes',
			'Number of 1st, 2nd then 3rd Place Finishes',
			'Number of 1st, 2nd, 3rd then 4th Place Finishes',
			'Number of 1st, 2nd, 3rd, 4th then 5th Place Finishes',
		])
		self.numPlacesTieBreaker.SetLabel( u'If Riders are still Tied on Points:' )
		bsizer.Add( self.numPlacesTieBreaker, 0, flag=wx.ALL|wx.EXPAND, border=2 )
		self.ifRidersAreStillTiedOnPoints = wx.StaticText(self, label=u'Points are considered separately by Grade.  If Riders are still Tied on Points, use most Recent Results')
		bsizer.Add( self.ifRidersAreStillTiedOnPoints, flag=wx.ALL, border=4 )

		self.headerNames = ['Name', 'OldName', 'Depth', 'Points for Position', 'Participation', 'DNF']
		
		self.grid = ReorderableGrid( self, style = wx.BORDER_SUNKEN )
		self.grid.DisableDragRowSize()
		self.grid.SetRowLabelSize( 64 )
		self.grid.CreateGrid( 50, len(self.headerNames) )
		for col in range(self.grid.GetNumberCols()):
			self.grid.SetColLabelValue( col, self.headerNames[col] + (u'       ' if  self.headerNames[col] == 'DNF' else '') )
		
		attr = gridlib.GridCellAttr()
		attr.SetReadOnly( True )
		attr.SetAlignment( wx.ALIGN_CENTRE, wx.ALIGN_CENTRE )
		self.grid.SetColAttr( self.DepthCol, attr )
		
		attr = gridlib.GridCellAttr()
		attr.SetEditor( PointsEditor() )
		self.grid.SetColAttr( self.PointsCol, attr )
		
		for c in (self.ParticipationCol, self.DNFCol):
			attr = gridlib.GridCellAttr()
			attr.SetRenderer( wx.grid.GridCellNumberRenderer() )
			attr.SetEditor( wx.grid.GridCellNumberEditor(0, 10000) )
			self.grid.SetColAttr( c, attr )
		
		self.gridAutoSize()

		sizer = wx.BoxSizer(wx.VERTICAL)
		sizer.Add(bsizer, 0, flag=wx.EXPAND|wx.ALL, border = 4 )
		self.pointsStructures = wx.StaticText(self, wx.ID_ANY, 'Points Structures:')
		sizer.Add( self.pointsStructures, 0, flag=wx.ALL, border = 4 )
		sizer.Add(self.grid, 1, flag=wx.EXPAND|wx.ALL, border = 6)
		self.SetSizer(sizer)
		
		self.scoreByPointsControls = [
			self.ifRidersTiedOnPoints,
			self.mostEventsCompleted,
			self.numPlacesTieBreaker,
			self.ifRidersAreStillTiedOnPoints,
			self.pointsStructures,
			self.grid,
		]
		
	def getGrid( self ):
		return self.grid
	
	def gridAutoSize( self ):
		self.grid.AutoSize()
		self.grid.SetColMinimalAcceptableWidth( 0 )
		self.grid.SetColMinimalWidth( self.OldNameCol, 0 )
		self.grid.SetColSize( self.OldNameCol, 0 )
		self.grid.EnableDragGridSize( False )
		self.grid.EnableDragColSize( False )
		self.Layout()
		self.Refresh()
	
	def updateDepth( self, row ):
		v = self.grid.GetCellValue(row, self.PointsCol).strip()
		depth = six.text_type(len(v.split())) if v else u''
		self.grid.SetCellValue( row, self.DepthCol, depth )
	
	def onGridChange( self, event ):
		row = event.GetRow()
		if row >= 0:
			self.updateDepth( row )
		wx.CallAfter( self.gridAutoSize )
	
	def fixEnable( self, event = None ):
		enable = self.scoreByPoints.GetValue()
		for c in self.scoreByPointsControls:
			c.Enable( enable )
	
	def refresh( self ):
		model = SeriesModel.model
		for row in range(self.grid.GetNumberRows()):
			for col in range(self.grid.GetNumberCols()):
				self.grid.SetCellValue( row, col, '' )
		
		for row, ps in enumerate(model.pointStructures):
			self.grid.SetCellValue( row, self.NameCol, ps.name )
			self.grid.SetCellValue( row, self.OldNameCol, ps.name )
			self.grid.SetCellValue( row, self.PointsCol, ps.getStr() )
			self.grid.SetCellValue( row, self.ParticipationCol, six.text_type(ps.participationPoints) )
			self.grid.SetCellValue( row, self.DNFCol, six.text_type(ps.dnfPoints) )
			self.updateDepth( row )
			
		wx.CallAfter( self.gridAutoSize )
		
		self.considerPrimePointsOrTimeBonus.SetValue( model.considerPrimePointsOrTimeBonus )
		self.bestResultsToConsider.SetSelection( model.bestResultsToConsider )
		self.mustHaveCompleted.SetSelection( model.mustHaveCompleted )
		
		self.mostEventsCompleted.SetValue( model.useMostEventsCompleted )
		self.numPlacesTieBreaker.SetSelection( model.numPlacesTieBreaker )
		
		if model.scoreByTime:
			self.scoreByTime.SetValue( True )
		elif model.scoreByPercent:
			self.scoreByPercent.SetValue( True )
		elif model.scoreByTrueSkill:
			self.scoreByTrueSkill.SetValue( True )
		else:
			self.scoreByPoints.SetValue( True )
		self.fixEnable()
	
	def commit( self ):
		self.grid.SaveEditControlValue()
		self.grid.DisableCellEditControl()	# Make sure the current edit is committed.
		pointsList = []
		for row in range(self.grid.GetNumberRows()):
			if( self.grid.GetCellValue(row, self.NameCol).strip() ):
				pointsList.append( (self.grid.GetCellValue(row, self.NameCol),
									self.grid.GetCellValue(row, self.OldNameCol),
									self.grid.GetCellValue(row, self.PointsCol),
									self.grid.GetCellValue(row, self.ParticipationCol),
									self.grid.GetCellValue(row, self.DNFCol),
									) )
		
		model = SeriesModel.model
		model.setPoints( pointsList )
		
		modelUpdate = {
			'considerPrimePointsOrTimeBonus': self.considerPrimePointsOrTimeBonus.GetValue(),
			'bestResultsToConsider': self.bestResultsToConsider.GetSelection(),
			'mustHaveCompleted': self.mustHaveCompleted.GetSelection(),
			'useMostEventsCompleted': self.mostEventsCompleted.GetValue(),
			'numPlacesTieBreaker': self.numPlacesTieBreaker.GetSelection(),
			'scoreByTime': self.scoreByTime.GetValue(),
			'scoreByPercent': self.scoreByPercent.GetValue(),
			'scoreByTrueSkill': self.scoreByTrueSkill.GetValue(),
		}
		
		for attr, value in six.iteritems(modelUpdate):
			if getattr(model, attr) != value:
				setattr( model, attr, value )
				model.setChanged()
Exemplo n.º 9
0
class Primes( wx.Panel ):
	def __init__( self, parent, id=wx.ID_ANY, size=wx.DefaultSize ):
		super(Primes, self).__init__( parent, id, size=size )
		
		self.state = RaceInputState()
		
		vsOverall = wx.BoxSizer( wx.VERTICAL )
		
		#---------------------------------------------------------------
		self.colNameFields = (
			(_('Prime For'),			'effortType',	's'),
			(_('or Custom'),			'effortCustom',	's'),
			(_('Position'),				'position',		'i'),
			(_('Laps\nTo Go'),			'lapsToGo',		'i'),
			(_('Sponsor'),				'sponsor', 		's'),
			(_('Cash'),					'cash', 		'f'),
			(_('Merchandise'),			'merchandise', 	's'),
			(_('Points'),				'points', 		'i'),
			(_('Time\nBonus'),			'timeBonus', 	't'),
			(_('Winner\nBib'),			'winnerBib',	'i'),
			(u'',						'winnerInfo',	's'),
		)
		self.colnames = [colName for colName, fieldName, dataType in self.colNameFields]
		self.iCol = dict( (fieldName, i) for i, (colName, fieldName, dataType) in enumerate(self.colNameFields) if fieldName )
		self.grid = ReorderableGrid( self )
		self.grid.CreateGrid( 0, len(self.colNameFields) )
		GetTranslation = _
		for col, (colName, fieldName, dataType) in enumerate(self.colNameFields):
			self.grid.SetColLabelValue( col, colName )
			attr = wx.grid.GridCellAttr()
			if fieldName == 'effortType':
				attr.SetEditor( wx.grid.GridCellChoiceEditor(choices=[GetTranslation(name) for code, name in EffortChoices]) )
				attr.SetAlignment( wx.ALIGN_CENTRE, wx.ALIGN_TOP )
			elif fieldName == 'position':
				attr.SetAlignment( wx.ALIGN_CENTRE, wx.ALIGN_TOP )
			elif fieldName == 'winnerInfo':
				attr.SetReadOnly( True )
			elif dataType == 'i':
				attr.SetAlignment( wx.ALIGN_RIGHT, wx.ALIGN_TOP )
				attr.SetEditor( wx.grid.GridCellFloatEditor(precision=0) )
				attr.SetRenderer( wx.grid.GridCellFloatRenderer(precision=0) )
			elif dataType == 'f':
				attr.SetAlignment( wx.ALIGN_RIGHT, wx.ALIGN_TOP )
				attr.SetEditor( wx.grid.GridCellFloatEditor(precision=2) )
				attr.SetRenderer( wx.grid.GridCellFloatRenderer(precision=2) )
			elif dataType == 't':
				attr.SetAlignment( wx.ALIGN_CENTRE, wx.ALIGN_CENTRE )
				attr.SetEditor( TimeEditor() )
			
			self.grid.SetColAttr( col, attr )
			if fieldName == 'lapsToGo':
				self.lapsToGoCol = col
		
		self.grid.Bind( wx.grid.EVT_GRID_CELL_CHANGED, self.onCellChange )
		self.grid.AutoSizeColumns( False )
		self.grid.AutoSizeRows( False )

		#---------------------------------------------------------------
		self.photosButton = wx.Button( self, label=u'{}...'.format(_('Photos')) )
		self.photosButton.Bind( wx.EVT_BUTTON, self.onPhotos )
		self.finishStrip = wx.Button( self, label=u'{}...'.format(_('Finish Strip')) )
		self.finishStrip.Bind( wx.EVT_BUTTON, self.onFinishStrip )
		self.history = wx.Button( self, label=u'{}...'.format(_('Passings')) )
		self.history.Bind( wx.EVT_BUTTON, self.onHistory )
		
		self.newButton = wx.Button( self, id=wx.ID_NEW )
		self.newButton.SetToolTip( wx.ToolTip(_('Create a new Prime')) )
		self.newButton.Bind( wx.EVT_BUTTON, self.onNew )
		self.nextPositionButton = wx.Button( self, label=('Next Position') )
		self.nextPositionButton.SetToolTip( wx.ToolTip(_('Create a Prime from an Existing Prime for the Next Position')) )
		self.nextPositionButton.Bind( wx.EVT_BUTTON, self.onNextPosition )
		self.nextPrimeButton = wx.Button( self, label=('Next Prime') )
		self.nextPrimeButton.SetToolTip( wx.ToolTip(_('Create a Prime from an Existing Prime')) )
		self.nextPrimeButton.Bind( wx.EVT_BUTTON, self.onNextPrime )
		self.deleteButton = wx.Button( self, id=wx.ID_DELETE )
		self.deleteButton.SetToolTip( wx.ToolTip(_('Delete a Prime')) )
		self.deleteButton.Bind( wx.EVT_BUTTON, self.onDelete )
		hsButtons = wx.BoxSizer( wx.HORIZONTAL )
		hsButtons.Add( self.photosButton, flag=wx.ALL, border=4 )
		hsButtons.Add( self.finishStrip, flag=wx.ALL, border=4 )
		hsButtons.Add( self.history, flag=wx.ALL, border=4 )
		hsButtons.AddStretchSpacer()
		hsButtons.Add( self.newButton, flag=wx.ALL, border=4 )
		hsButtons.Add( self.nextPositionButton, flag=wx.ALL, border=4 )
		hsButtons.Add( self.nextPrimeButton, flag=wx.ALL, border=4 )
		hsButtons.Add( self.deleteButton, flag=wx.ALL, border=4 )
		
		#---------------------------------------------------------------
		
		vsOverall.Add( self.grid, 1, flag=wx.EXPAND|wx.ALL, border=4 )
		vsOverall.Add( hsButtons, flag=wx.EXPAND|wx.LEFT|wx.RIGHT|wx.BOTTOM, border=4 )
		self.SetSizer( vsOverall )
	
	def onCellChange( self, event ):
		row, col = event.GetRow(), event.GetCol()
		colName = self.colNameFields[col][1]
		GetTranslation = _
		if colName == 'effortCustom':
			if self.grid.GetCellValue(row, col).strip():
				self.grid.SetCellValue( row, col-1, GetTranslation('Custom') )
		elif colName == 'effortType':
			if self.grid.GetCellValue(row, col) != 'Custom':
				self.grid.SetCellValue( row, col+1, u'' )
		elif colName == 'winnerBib':
			bib = int( u''.join(c for c in self.grid.GetCellValue(row, col) if c.isdigit()) )
			self.grid.SetCellValue( row, col+1, getWinnerInfo(bib) )
		
		wx.CallAfter( self.grid.AutoSizeColumns, False )
	
	def getT( self ):
		race = Model.race
		if not race:
			return 0
		row = self.grid.GetGridCursorRow()
		if row is None or row < 0:
			return
		lapsToGo = int( u''.join(c for c in self.grid.GetCellValue(row, self.lapsToGoCol) if c.isdigit()) )
		tMax = 0.0
		for rr in GetResults(None):
			try:
				tMax = min( tMax, rr.raceTimes[-1-lapsToGo] )
			except IndexError:
				pass
		return tMax
		
	def onPhotos( self, event ):
		mainWin = Utils.getMainWin()
		if not mainWin:
			return
		mainWin.photoDialog.SetT( self.getT() )
		mainWin.photoDialog.Show()
		
	def onFinishStrip( self, event ):
		ShowFinishStrip( self, self.getT() )
	
	def onHistory( self, event ):
		mainWin = Utils.getMainWin()
		if not mainWin:
			return
		mainWin.openMenuWindow( 'Passings' )
	
	def selectGridRow( self, row ):
		self.grid.SelectRow( row )
		self.grid.SetGridCursor( row, 0 )
		self.grid.ShowCellEditControl()
	
	def onNew( self, event ):
		race = Model.race
		if not race:
			Utils.MessageOK( self, _('You must have a Race to create a Prime.'), _('Missing Race') )
			return
		self.commit()
		race.primes = getattr(race, 'primes', [])
		rowNew = len( race.primes )
		race.primes.append( {} )
		self.updateGrid()
		self.selectGridRow( rowNew )
	
	def onNextPosition( self, event ):
		rowNext = self.grid.GetGridCursorRow()
		if rowNext is None or rowNext < 0:
			return
		self.commit()
		race = Model.race
		if not race:
			Utils.MessageOK( self, _('You must have a Race to create a next Prime.'), _('Missing Race') )
			return
		
		nextPrime = race.primes[rowNext].copy()
		
		nextPoints = {
			(1, 5):	3,
			(2, 3): 2,
			(3, 2): 1,
		}.get( (nextPrime['position'], nextPrime['points']), None )
		
		if nextPoints is not None:
			nextPrime['points'] = nextPoints
		
		try:
			nextPrime['position'] += 1
		except:
			pass
		nextPrime['winnerBib'] = None
		race.primes = race.primes[:rowNext+1] + [nextPrime] + race.primes[rowNext+1:]
		self.updateGrid()
		self.selectGridRow( rowNext + 1 )
	
	def onNextPrime( self, event ):
		rowNext = self.grid.GetGridCursorRow()
		if rowNext is None or rowNext < 0:
			return
		self.commit()
		race = Model.race
		if not race:
			Utils.MessageOK( self, _('You must have a Race to create a next Prime.'), _('Missing Race') )
			return
		nextPrime = race.primes[rowNext].copy()
		nextPrime['position'] = 1
		if nextPrime['points']:
			nextPrime['points'] = 5
		if nextPrime['lapsToGo'] > 0:
			nextPrime['lapsToGo'] -= 1
		nextPrime['winnerBib'] = None
		race.primes = race.primes[:rowNext+1] + [nextPrime] + race.primes[rowNext+1:]
		self.updateGrid()
		self.selectGridRow( rowNext + 1 )
		
	def onDelete( self, event ):
		rowDelete = self.grid.GetGridCursorRow()
		if rowDelete is None or rowDelete < 0:
			return
		self.commit()
		race = Model.race
		if race and Utils.MessageOKCancel( self, u'{}: {} ?'.format(_('Delete Prime'), rowDelete+1), _('Confirm Delete Primes') ):
			race.primes = getattr(race, 'primes', [])
			try:
				del race.primes[rowDelete]
			except Exception as e:
				return
			self.updateGrid()
			if race.primes:
				self.grid.SetGridCursor( rowDelete, 0 )
		
	def getSponsors( self ):
		race = Model.race
		if not race:
			return []
		sponsors = [prime.get('sponsor', u'') for prime in getattr(race, 'primes', [])] + [race.organizer]
		sponsors = [s for s in sponsors if s]
		return sponsors
		
	def getMerchandise( self ):
		race = Model.race
		if not race:
			return []
		merchandise = [prime.get('merchandise', u'') for prime in getattr(race, 'primes', [])]
		merchandise = [m for m in merchandise if m]
		return merchandise
	
	def setRow( self, prime, row, updateGrid=True ):
		GetTranslation = _
		
		data = []
		for col, (name, attr, dataType) in enumerate(self.colNameFields):
			if attr == 'effortType':
				effortType = prime.get('effortType', 'Pack')
				v = GetTranslation(effortType)
			elif attr == 'position':
				position = prime.get('position', 1)
				v = u'' if position == 0 else unicode(position)
			elif attr == 'points':
				points = prime.get('points', 0)
				v = u'' if points == 0 else unicode(points)
			elif attr == 'winnerBib':
				winnerBib = prime.get('winnerBib', None)
				v = u'' if not winnerBib else unicode(winnerBib)
			elif attr == 'winnerInfo':
				v = getWinnerInfo(winnerBib)
			elif dataType == 'f':
				f = prime.get(attr, 0.0)
				v = u'{:.2f}'.format(f) if f else u''
			elif dataType == 't':
				t = prime.get(attr, 0.0)
				v = Utils.formatTime(t, forceHours=True, twoDigitHours=True) if t != 0 else u''
			else:
				v = unicode(prime.get(attr, u''))
			if updateGrid:
				self.grid.SetCellValue( row, col, v )
			data.append( v )
		
		return data
	
	def getRow( self, row ):
		values = {}
		for col, (name, attr, dataType) in enumerate(self.colNameFields):
			v = self.grid.GetCellValue( row, col ).strip()
			if dataType == 'i':
				v = u''.join( c for c in v if c.isdigit() )
				v = int( v or 0 )
			elif dataType == 'f':
				v = u''.join( c for c in v if c.isdigit() or c == '.')
				v = float( v or 0.0 )
			elif dataType == 't':
				v = Utils.StrToSeconds( v )
				
			if attr == 'position' and not v:
				v = 1
			
			values[attr] = v
		
		GetTranslation = _
		for code, name in EffortChoices:
			if values['effortType'] == GetTranslation(name):
				values['effortType'] = name
				break
		
		if values['effortCustom']:
			values['effortType'] = 'Custom'
		return values
	
	def updateGrid( self ):
		race = Model.race
		if not race or not getattr(race, 'primes', None):
			self.grid.ClearGrid()
			return
		
		Utils.AdjustGridSize( self.grid, len(race.primes) )
		for row, prime in enumerate(race.primes):
			self.setRow( prime, row )
		
		self.grid.AutoSizeColumns( False )								# Resize to fit the column name.
		self.grid.AutoSizeRows( False )
	
	def refresh( self ):
		if self.state.changed():
			self.updateGrid()
		
	def commit( self ):
		self.grid.SaveEditControlValue()	# Make sure the current edit is committed.
		self.grid.DisableCellEditControl()
		race = Model.race
		if not race:
			return
		race.primes = [self.getRow(row) for row in xrange(self.grid.GetNumberRows())]
Exemplo n.º 10
0
class Races(wx.Panel):
	#----------------------------------------------------------------------
	RaceCol = 0
	PointsCol = 1
	RaceFileCol = 2
	RaceStatusCol = 3
	
	def __init__(self, parent):
		wx.Panel.__init__(self, parent)
		
		self.seriesNameLabel = wx.StaticText( self, label='Series Name:' )
		self.seriesName = wx.TextCtrl( self )

		self.organizerNameLabel = wx.StaticText( self, label='Organizer:' )
		self.organizerName = wx.TextCtrl( self )
		
		self.explanation = wx.StaticText( self, label=u'\n'.join( [
				_("Add all the races in your Series."),
				_("Make sure the races are in chronological order."),
				_("You can change the order by dragging-and-dropping the first grey column in the table."),
				u'',
				_("Configure the Points Structures or Time Scoring parameters on the Scoring Criteria page."),
				_("Each race can have its own Points Structure.  For example, you could create 'Double Points' for one race."),
				u'',
				_("Race results are shown Last-to-First in the output by default."),
				_("You can change this on the Options page."),
			] )
		)
		
		self.headerNames = ['Race', 'Points', 'Race File']
		
		self.grid = ReorderableGrid( self, style = wx.BORDER_SUNKEN )
		self.grid.DisableDragRowSize()
		self.grid.SetRowLabelSize( 64 )
		self.grid.CreateGrid( 0, len(self.headerNames) )
		for col in xrange(self.grid.GetNumberCols()):
			self.grid.SetColLabelValue( col, self.headerNames[col] )
		
		self.pointsChoiceEditor = gridlib.GridCellChoiceEditor([], allowOthers=False)
		attr = gridlib.GridCellAttr()
		attr.SetEditor( self.pointsChoiceEditor )
		self.grid.SetColAttr( self.PointsCol, attr )
		
		attr = gridlib.GridCellAttr()
		attr.SetReadOnly( True )
		self.grid.SetColAttr( self.RaceCol, attr )
		
		'''
		attr = gridlib.GridCellAttr()
		attr.SetReadOnly( True )
		self.grid.SetColAttr( self.RaceStatusCol, attr )
		'''
		
		attr = gridlib.GridCellAttr()
		attr.SetReadOnly( True )
		self.grid.SetColAttr( self.RaceFileCol, attr )
		
		self.grid.Bind( gridlib.EVT_GRID_CELL_CHANGED, self.onGridChange )
		self.gridAutoSize()
		self.grid.Bind( wx.grid.EVT_GRID_EDITOR_CREATED, self.onGridEditorCreated )
		self.grid.Bind( wx.grid.EVT_GRID_CELL_LEFT_CLICK, self.onEditRaceFileName )
		
		self.addButton = wx.Button( self, wx.ID_ANY, 'Add Races' )
		self.addButton.Bind( wx.EVT_BUTTON, self.doAddRace )

		self.removeButton = wx.Button( self, wx.ID_ANY, 'Remove Race' )
		self.removeButton.Bind( wx.EVT_BUTTON, self.doRemoveRace )

		fgs = wx.FlexGridSizer( rows=2, cols=2, vgap=2, hgap=2 )
		fgs.AddGrowableCol( 1, proportion=1 )
		
		fgs.Add( self.seriesNameLabel, flag=wx.ALIGN_CENTRE_VERTICAL|wx.ALIGN_RIGHT )
		fgs.Add( self.seriesName, flag=wx.EXPAND )
		fgs.Add( self.organizerNameLabel, flag=wx.ALIGN_CENTRE_VERTICAL|wx.ALIGN_RIGHT )
		fgs.Add( self.organizerName, flag=wx.EXPAND )
		
		hs = wx.BoxSizer( wx.HORIZONTAL )
		hs.Add( self.addButton, 0, flag=wx.ALL, border = 4 )
		hs.Add( self.removeButton, 0, flag=wx.ALL, border = 4 )
		
		sizer = wx.BoxSizer(wx.VERTICAL)
		sizer.Add(fgs, 0, flag=wx.EXPAND|wx.ALL, border=4 )
		sizer.Add( self.explanation, 0, flag=wx.EXPAND|wx.ALL, border=4 )
		sizer.Add(hs, 0, flag=wx.EXPAND)
		sizer.Add(self.grid, 1, flag=wx.EXPAND|wx.ALL, border = 6)
		self.SetSizer(sizer)

	def getGrid( self ):
		return self.grid
	
	wildcard = 'CrossMgr or Excel files (*.cmn, *.xlsx, *.xlsm, *.xls)|*.cmn;*.xlsx;*.xlsm;*.xls;'
	
	def onEditRaceFileName( self, event ):
		col = event.GetCol()
		if col != self.RaceFileCol:
			event.Skip()
			return
			
		row = event.GetRow()
		dlg = wx.FileDialog( self, message="Choose a CrossMgr or Excel file",
					defaultFile = '',
					wildcard = self.wildcard,
					style=wx.FD_OPEN | wx.FD_CHANGE_DIR )
		ret = dlg.ShowModal()
		fileName = ''
		if ret == wx.ID_OK:
			fileName = dlg.GetPath()
			self.grid.SetCellValue( row, self.RaceCol, SeriesModel.RaceNameFromPath(fileName) )
			self.grid.SetCellValue( row, self.RaceFileCol, fileName )
		dlg.Destroy()
		self.commit()
	
	def doAddRace( self, event ):
		dlg = wx.FileDialog( self, message="Choose a CrossMgr or Excel file",
					defaultFile = '',
					wildcard = self.wildcard,
					style=wx.FD_OPEN | wx.FD_CHANGE_DIR | wx.FD_MULTIPLE )
		ret = dlg.ShowModal()
		if ret == wx.ID_OK:
			for fileName in dlg.GetPaths():
				SeriesModel.model.addRace( fileName )
		dlg.Destroy()
		self.refresh()
		
	def doRemoveRace( self, event ):
		row = self.grid.GetGridCursorRow()
		if row < 0:
			Utils.MessageOK(self, 'No Selected Race.\nPlease Select a Race to Remove.', 'No Selected Race')
			return
		if Utils.MessageOKCancel(self, 'Confirm Remove Race:\n\n    {}'.format( self.grid.GetCellValue(row, 0) ), 'Remove Race'):
			self.grid.DeleteRows( row )
			self.commit()
	
	def updatePointsChoices( self ):
		try:
			comboBox = self.comboBox
		except AttributeError:
			return
		comboBox.SetItems( [p.name for p in SeriesModel.model.pointStructures] )
	
	def onGridEditorCreated(self, event):
		if event.GetCol() == self.PointsCol:
			self.comboBox = event.GetControl()
			self.updatePointsChoices()
		event.Skip()

	def gridAutoSize( self ):
		self.grid.AutoSize()
		self.grid.EnableDragGridSize( False )
		self.grid.EnableDragColSize( False )
		self.Layout()
		self.Refresh()
	
	def onGridChange( self, event ):
		wx.CallAfter( self.gridAutoSize )
	
	def refresh( self ):
		model = SeriesModel.model
		Utils.AdjustGridSize( self.grid, len(model.races) )
		for row, race in enumerate(model.races):
			self.grid.SetCellValue( row, self.RaceCol, race.getRaceName() )
			self.grid.SetCellValue( row, self.PointsCol, race.pointStructure.name )
			self.grid.SetCellValue( row, self.RaceFileCol, race.fileName )
		wx.CallAfter( self.gridAutoSize )
		
		self.seriesName.SetValue( SeriesModel.model.name )
		self.organizerName.SetValue( SeriesModel.model.organizer )
	
	def commit( self ):
		self.grid.SaveEditControlValue()
		self.grid.DisableCellEditControl()	# Make sure the current edit is committed.
		
		raceList = []
		for row in xrange(self.grid.GetNumberRows()):
			race = SeriesModel.model.races[row]
			fileName = self.grid.GetCellValue(row, self.RaceFileCol).strip()
			pname = self.grid.GetCellValue( row, self.PointsCol )
			if not fileName or not pname:
				continue
			raceList.append( (fileName, pname) )
		
		model = SeriesModel.model
		model.setRaces( raceList )
		
		if self.seriesName.GetValue() != model.name:
			model.name = self.seriesName.GetValue()
			model.changed = True
			
		if self.organizerName.GetValue() != model.organizer:
			model.organizer = self.organizerName.GetValue()
			model.changed = True
			
		wx.CallAfter( self.refresh )
Exemplo n.º 11
0
class Prizes(wx.Panel):
    rowsMax = 20

    def __init__(self, parent, id=wx.ID_ANY, size=wx.DefaultSize):
        super(Prizes, self).__init__(parent, id, size=size)

        vsOverall = wx.BoxSizer(wx.VERTICAL)

        self.grid = ReorderableGrid(self)
        self.grid.CreateGrid(0, 10)

        self.grid.AutoSizeColumns(False)
        self.grid.AutoSizeRows(False)

        self.grid.Bind(wx.grid.EVT_GRID_CELL_CHANGED, self.onCellChange)

        #---------------------------------------------------------------

        vsOverall.Add(self.grid, 1, flag=wx.EXPAND | wx.ALL, border=4)
        self.SetSizer(vsOverall)

    def onCellChange(self, event):
        race = Model.race
        if not race:
            return
        row, col = event.GetRow(), event.GetCol()
        if col & 1:
            return
        categories = race.getCategories(startWaveOnly=False, publishOnly=True)
        if self.grid.GetNumberCols() != len(categories) * 2:
            Utils.AdjustGridSize(self.grid, self.rowsMax, len(categories) * 2)
        if row >= self.grid.GetNumberRows() or col >= self.grid.GetNumberCols(
        ):
            return
        self.copyToRace()
        try:
            category = categories[col // 2]
        except IndexError:
            return
        self.grid.SetCellValue(
            row, col + 1,
            self.getRecepient(self.grid.GetCellValue(row, col), row, category))
        wx.CallAfter(self.grid.AutoSizeColumns, False)

    def getRecepient(self, prize, row, category):
        if not prize:
            return ''
        name = ''
        results = GetResults(category)
        try:
            name = u'{}: {}'.format(results[row].num, results[row].full_name())
        except IndexError:
            pass
        return name

    def setCellPair(self, row, col, category):
        try:
            prize = getattr(category, 'prizes', [])[row]
        except IndexError:
            prize = ''
        self.grid.SetCellValue(row, col, prize)
        self.grid.SetCellValue(row, col + 1,
                               self.getRecepient(prize, row, category))

    def updateGrid(self):
        race = Model.race
        if not race:
            self.grid.ClearGrid()
            return
        categories = race.getCategories(startWaveOnly=False, publishOnly=True)
        Utils.AdjustGridSize(self.grid, self.rowsMax, len(categories) * 2)
        col = 0
        for category in categories:
            fullname = category.fullname
            ib = fullname.rfind('(')
            catname, catgender = fullname[:ib].strip(), fullname[ib:]
            colName = '{}\n{}'.format(catname, catgender)
            self.grid.SetColLabelValue(col, colName)
            attr = wx.grid.GridCellAttr()
            attr.SetReadOnly(False)
            attr.SetAlignment(wx.ALIGN_CENTRE, wx.ALIGN_CENTRE)
            self.grid.SetColAttr(col, attr)

            self.grid.SetColLabelValue(col + 1, _('Recipient'))
            attr = wx.grid.GridCellAttr()
            attr.SetReadOnly(True)
            attr.SetAlignment(wx.ALIGN_LEFT, wx.ALIGN_CENTRE)
            attr.SetBackgroundColour(wx.Colour(152, 251, 152))
            self.grid.SetColAttr(col + 1, attr)

            for row in range(self.rowsMax):
                self.setCellPair(row, col, category)
            col += 2

        self.grid.AutoSizeColumns(False)  # Resize to fit the column name.
        self.grid.AutoSizeRows(False)

    def refresh(self):
        self.updateGrid()

    def copyToRace(self):
        race = Model.race
        if not race:
            return

        categories = race.getCategories(startWaveOnly=False, publishOnly=True)
        for i, category in enumerate(categories):
            prizes = []
            for row in range(self.rowsMax):
                v = self.grid.GetCellValue(row, i * 2).strip()
                if not v:
                    break
                prizes.append(v)
            category.prizes = prizes

    def commit(self):
        self.grid.SaveEditControlValue(
        )  # Make sure the current edit is committed.
        self.grid.DisableCellEditControl()
        self.copyToRace()
Exemplo n.º 12
0
class Chart(wx.Panel):
    """"""

    #----------------------------------------------------------------------
    def __init__(self, parent):
        wx.Panel.__init__(self, parent)

        font = GetFont()

        self.title = wx.StaticText(self, wx.ID_ANY, "Competition Table:")
        self.title.SetFont(font)
        self.showNames = wx.ToggleButton(self, wx.ID_ANY, 'Show Names')
        self.showNames.SetFont(font)
        self.showNames.Bind(wx.EVT_TOGGLEBUTTON, self.onToggleShow)
        self.showTeams = wx.ToggleButton(self, wx.ID_ANY, 'Show Teams')
        self.showTeams.SetFont(font)
        self.showTeams.Bind(wx.EVT_TOGGLEBUTTON, self.onToggleShow)

        self.headerNames = [
            '', 'System', 'Event', 'Heats', 'In', 'Bib', 'Name', 'Team', 'H1',
            'H2', 'H3', 'Out', 'Bib', 'Name', 'Team'
        ]
        self.numericFields = set(['Event', 'Heats', 'Bib', 'In', 'Out'])

        self.grid = ReorderableGrid(self, style=wx.BORDER_SUNKEN)
        self.grid.DisableDragRowSize()
        self.grid.SetRowLabelSize(0)
        self.grid.EnableReorderRows(False)
        self.grid.CreateGrid(0, len(self.headerNames))
        self.setColNames()

        # Set a larger font for the table.
        # Set specialized editors for appropriate columns.
        self.grid.SetLabelFont(font)

        sizer = wx.BoxSizer(wx.VERTICAL)
        hs = wx.BoxSizer(wx.HORIZONTAL)
        hs.Add(self.title, 0, flag=wx.ALL | wx.ALIGN_CENTRE_VERTICAL, border=4)
        hs.Add(self.showNames, 0, flag=wx.ALL, border=4)
        hs.Add(self.showTeams, 0, flag=wx.ALL, border=4)

        sizer.Add(hs, flag=wx.ALL, border=4)
        sizer.Add(self.grid, 1, flag=wx.EXPAND | wx.ALL, border=6)
        self.SetSizer(sizer)

    def onToggleShow(self, e):
        model = Model.model
        model.chartShowNames = self.showNames.GetValue()
        model.chartShowTeams = self.showTeams.GetValue()
        self.refresh()

    def getHideCols(self, headerNames):
        model = Model.model
        toHide = set()
        for col, h in enumerate(headerNames):
            if h == 'Name' and not getattr(model, 'chartShowNames', True):
                toHide.add(col)
            elif h == 'Team' and not getattr(model, 'chartShowTeams', True):
                toHide.add(col)
        return toHide

    def setColNames(self):
        for col, headerName in enumerate(self.headerNames):
            self.grid.SetColLabelValue(col, headerName)

    def getGrid(self):
        return self.grid

    def refresh(self):
        model = Model.model
        competition = model.competition
        state = competition.state

        self.showNames.SetValue(getattr(model, 'chartShowNames', True))
        self.showTeams.SetValue(getattr(model, 'chartShowTeams', True))

        font = GetFont()

        self.headerNames = [
            '', 'System', 'Event', 'Heats', 'In', 'Bib', 'Name', 'Team', 'H1',
            'H2', 'H3', 'Out', 'Bib', 'Name', 'Team'
        ]
        hideCols = self.getHideCols(self.headerNames)
        self.headerNames = [
            h for c, h in enumerate(self.headerNames) if c not in hideCols
        ]
        Utils.AdjustGridSize(self.grid,
                             rowsRequired=sum(
                                 1 for t, s, e in competition.allEvents()),
                             colsRequired=len(self.headerNames))
        self.grid.ClearGrid()
        self.setColNames()

        for col in six.moves.range(self.grid.GetNumberCols()):
            attr = gridlib.GridCellAttr()
            attr.SetFont(font)
            attr.SetReadOnly(True)
            if col >= 4:
                attr.SetRenderer(GridCellMultiLineStringRenderer())
            if self.headerNames[col] in self.numericFields:
                attr.SetAlignment(wx.ALIGN_CENTRE, wx.ALIGN_TOP)
            elif self.headerNames[col].startswith('H'):
                attr.SetAlignment(wx.ALIGN_CENTRE, wx.ALIGN_TOP)
            self.grid.SetColAttr(col, attr)

        row = 0
        for tournament in competition.tournaments:
            self.grid.SetCellValue(row, 0, tournament.name)
            for system in tournament.systems:
                self.grid.SetCellValue(row, 1, system.name)
                for i, event in enumerate(system.events):
                    writeCell = WriteCell(self.grid, row, 2)

                    writeCell(u'{}'.format(i + 1))
                    writeCell(u' {}'.format(event.heatsMax))
                    writeCell(u'\n'.join(event.composition).replace(
                        u'\n', u' ({})\n'.format(len(event.composition)), 1))

                    riders = [
                        state.labels.get(c, None) for c in event.composition
                    ]
                    writeCell(u'\n'.join([
                        u'{}'.format(rider.bib if rider.bib else u'')
                        if rider else '' for rider in riders
                    ]))
                    if getattr(model, 'chartShowNames', True):
                        writeCell(u'\n'.join([
                            rider.full_name if rider else u''
                            for rider in riders
                        ]))
                    if getattr(model, 'chartShowTeams', True):
                        writeCell(u'\n'.join([
                            rider.team if rider else u'' for rider in riders
                        ]))

                    for heat in six.moves.range(3):
                        if event.heatsMax > 1:
                            writeCell(u'\n'.join(event.getHeatPlaces(heat +
                                                                     1)))
                        else:
                            writeCell(u'')

                    out = [event.winner] + event.others
                    writeCell(u'\n'.join(out).replace(
                        u'\n', u' ({})\n'.format(len(out)), 1))
                    riders = [state.labels.get(c, None) for c in out]
                    writeCell(u'\n'.join([
                        u'{}'.format(rider.bib if rider.bib else '')
                        if rider else '' for rider in riders
                    ]))
                    if getattr(model, 'chartShowNames', True):
                        writeCell('\n'.join([
                            rider.full_name if rider else ''
                            for rider in riders
                        ]))
                    if getattr(model, 'chartShowTeams', True):
                        writeCell('\n'.join(
                            [rider.team if rider else '' for rider in riders]))
                    row += 1

        self.grid.AutoSizeColumns(False)
        self.grid.AutoSizeRows(False)

    def commit(self):
        pass
Exemplo n.º 13
0
class Results(wx.Panel):
    #----------------------------------------------------------------------
    def __init__(self, parent):
        """Constructor"""
        wx.Panel.__init__(self, parent)

        self.font = wx.Font((0, FontSize), wx.FONTFAMILY_SWISS,
                            wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL)

        self.showResultsLabel = wx.StaticText(self, wx.ID_ANY, u'Show:')
        self.showResultsLabel.SetFont(self.font)
        self.showResults = wx.Choice(self, wx.ID_ANY, choices=['Qualifiers'])
        self.showResults.SetFont(self.font)
        self.showResults.SetSelection(0)

        self.communiqueLabel = wx.StaticText(self, wx.ID_ANY,
                                             u'Communiqu\u00E9:')
        self.communiqueLabel.SetFont(self.font)
        self.communiqueNumber = wx.TextCtrl(self, wx.ID_ANY, '', size=(80, -1))
        self.communiqueNumber.SetFont(self.font)

        self.showResults.Bind(wx.EVT_LEFT_DOWN, self.onClickResults)
        self.showResults.Bind(wx.EVT_CHOICE, self.onShowResults)
        self.showNames = wx.ToggleButton(self, wx.ID_ANY, u'Show Names')
        self.showNames.SetFont(self.font)
        self.showNames.Bind(wx.EVT_TOGGLEBUTTON, self.onToggleShow)
        self.showTeams = wx.ToggleButton(self, wx.ID_ANY, u'Show Teams')
        self.showTeams.SetFont(self.font)
        self.showTeams.Bind(wx.EVT_TOGGLEBUTTON, self.onToggleShow)
        self.competitionTime = wx.StaticText(self)

        self.headerNames = ['uPos', u'Bib', u'Rider', u'Team', u'License']

        self.grid = ReorderableGrid(self, style=wx.BORDER_SUNKEN)
        self.grid.DisableDragRowSize()
        self.grid.SetRowLabelSize(64)
        self.grid.CreateGrid(0, len(self.headerNames))
        self.grid.SetRowLabelSize(0)
        self.grid.EnableReorderRows(False)
        self.setColNames()

        sizer = wx.BoxSizer(wx.VERTICAL)

        hs = wx.BoxSizer(wx.HORIZONTAL)
        hs.Add(self.showResultsLabel,
               0,
               flag=wx.ALIGN_CENTRE_VERTICAL,
               border=4)
        hs.Add(self.showResults,
               0,
               flag=wx.ALIGN_CENTER_VERTICAL | wx.ALL,
               border=4)
        hs.Add(self.communiqueLabel,
               0,
               flag=wx.ALIGN_CENTER_VERTICAL | wx.ALL,
               border=4)
        hs.Add(self.communiqueNumber,
               0,
               flag=wx.ALIGN_CENTER_VERTICAL | wx.ALL | wx.EXPAND,
               border=4)
        hs.Add(self.showNames,
               flag=wx.ALIGN_CENTER_VERTICAL | wx.ALL,
               border=4)
        hs.Add(self.showTeams,
               flag=wx.ALIGN_CENTER_VERTICAL | wx.ALL,
               border=4)
        hs.Add(self.competitionTime,
               flag=wx.ALIGN_CENTER_VERTICAL | wx.ALL,
               border=4)

        sizer.Add(hs,
                  0,
                  flag=wx.EXPAND | wx.TOP | wx.LEFT | wx.RIGHT,
                  border=6)
        sizer.Add(self.grid, 1, flag=wx.EXPAND | wx.ALL, border=6)
        self.SetSizer(sizer)

    def onToggleShow(self, e):
        model = Model.model
        model.resultsShowNames = self.showNames.GetValue()
        model.resultsShowTeams = self.showTeams.GetValue()
        self.refresh()

    def setColNames(self):
        self.grid.SetLabelFont(self.font)
        for col, headerName in enumerate(self.headerNames):
            self.grid.SetColLabelValue(col, headerName)

            attr = gridlib.GridCellAttr()
            attr.SetFont(self.font)
            if self.headerNames[col] in {u'Bib', u'Event'}:
                attr.SetAlignment(wx.ALIGN_CENTRE, wx.ALIGN_TOP)
            elif u'Time' in self.headerNames[col]:
                attr.SetAlignment(wx.ALIGN_RIGHT, wx.ALIGN_TOP)
            elif self.headerNames[col] == u'Pos':
                attr.SetAlignment(wx.ALIGN_RIGHT, wx.ALIGN_TOP)
            elif Arrow in self.headerNames[col]:
                attr.SetAlignment(wx.ALIGN_CENTRE, wx.ALIGN_VERTICAL_CENTRE)
            elif self.headerNames[col].startswith(u'H'):
                attr.SetAlignment(wx.ALIGN_CENTRE, wx.ALIGN_TOP)
            attr.SetReadOnly(True)
            self.grid.SetColAttr(col, attr)

    def getResultChoices(self):
        model = Model.model
        competition = model.competition
        choices = [u'Qualifiers']
        for tournament in competition.tournaments:
            for system in tournament.systems:
                name = ('%s: ' % tournament.name
                        if tournament.name else '') + system.name
                choices.append(name)
        choices.append(u'Final Classification')
        return choices

    def fixShowResults(self):
        model = Model.model
        competition = model.competition

        choices = self.getResultChoices()
        self.showResults.SetItems(choices)

        if model.showResults >= len(choices):
            model.showResults = 0
        self.showResults.SetSelection(model.showResults)

    def getHideCols(self, headerNames):
        model = Model.model
        toHide = set()
        for col, h in enumerate(headerNames):
            if h == u'Name' and not getattr(model, 'resultsShowNames', True):
                toHide.add(col)
            elif h == u'Team' and not getattr(model, 'resultsShowTeams', True):
                toHide.add(col)
        return toHide

    def getGrid(self):
        return self.grid

    def getPhase(self, num=None):
        if num is None:
            num = self.showResults.GetSelection()
        choices = self.getResultChoices()
        return choices[num]

    def getTitle(self):
        phase = self.getPhase()
        title = u'Communiqu\u00E9: {}\n{} {} '.format(
            self.communiqueNumber.GetValue(), phase,
            '' if phase.startswith(u'Final') or phase.startswith('Time') else
            u'Draw Sheet/Intermediate Results')
        return title

    def onClickResults(self, event):
        self.commit()
        event.Skip()

    def onShowResults(self, event):
        Model.model.showResults = self.showResults.GetSelection()
        self.refresh()

    def refresh(self):
        self.fixShowResults()
        self.grid.ClearGrid()

        model = Model.model
        competition = model.competition

        self.showNames.SetValue(getattr(model, 'resultsShowNames', True))
        self.showTeams.SetValue(getattr(model, 'resultsShowTeams', True))

        self.communiqueNumber.SetValue(
            model.communique_number.get(self.getPhase(), ''))

        resultName = self.showResults.GetStringSelection()

        if 'Qualifiers' in resultName:
            starters = competition.starters

            self.headerNames = [u'Pos', u'Bib', u'Name', u'Team', u'Time']
            hideCols = self.getHideCols(self.headerNames)
            self.headerNames = [
                h for c, h in enumerate(self.headerNames) if c not in hideCols
            ]

            riders = sorted(model.riders, key=lambda r: r.keyQualifying())
            for row, r in enumerate(riders):
                if row >= starters or r.status == 'DNQ':
                    riders[row:] = sorted(riders[row:],
                                          key=lambda r: r.keyQualifying()[1:])
                    break
            Utils.AdjustGridSize(self.grid,
                                 rowsRequired=len(riders),
                                 colsRequired=len(self.headerNames))
            Utils.SetGridCellBackgroundColour(self.grid, wx.WHITE)
            self.setColNames()
            for row, r in enumerate(riders):
                if row < starters and r.status != 'DNQ':
                    pos = u'{}'.format(row + 1)
                    for col in six.moves.range(self.grid.GetNumberCols()):
                        self.grid.SetCellBackgroundColour(row, col, wx.WHITE)
                else:
                    pos = 'DNQ'
                    for col in six.moves.range(self.grid.GetNumberCols()):
                        self.grid.SetCellBackgroundColour(
                            row, col, wx.Colour(200, 200, 200))

                writeCell = WriteCell(self.grid, row)
                for col, value in enumerate([
                        pos, u' {}'.format(r.bib), r.full_name, r.team,
                        r.qualifyingTimeText
                ]):
                    if col not in hideCols:
                        writeCell(value)

            competitionTime = model.qualifyingCompetitionTime
            self.competitionTime.SetLabel(u'{}: {}'.format(
                _('Est. Competition Time'), Utils.formatTime(competitionTime)
            ) if competitionTime else u'')

        elif 'Final Classification' in resultName:
            self.headerNames = [u'Pos', u'Bib', u'Name', u'Team', u'License']
            hideCols = self.getHideCols(self.headerNames)
            self.headerNames = [
                h for c, h in enumerate(self.headerNames) if c not in hideCols
            ]

            results, dnfs, dqs = competition.getResults()
            Utils.AdjustGridSize(self.grid,
                                 rowsRequired=len(model.riders),
                                 colsRequired=len(self.headerNames))
            Utils.SetGridCellBackgroundColour(self.grid, wx.WHITE)

            self.setColNames()
            for row, (classification, r) in enumerate(results):
                writeCell = WriteCell(self.grid, row)
                if not r:
                    for col in six.moves.range(self.grid.GetNumberCols()):
                        writeCell('')
                else:
                    for col, value in enumerate([
                            classification, r.bib if r.bib else '',
                            r.full_name, r.team, r.license
                    ]):
                        if col not in hideCols:
                            writeCell(u' {}'.format(value))
            self.competitionTime.SetLabel(u'')
        else:
            # Find the Tournament and System selected.
            keepGoing = True
            for tournament in competition.tournaments:
                for system in tournament.systems:
                    name = (u'%s: ' % tournament.name
                            if tournament.name else '') + system.name
                    if name == resultName:
                        keepGoing = False
                        break
                if not keepGoing:
                    break

            heatsMax = max(event.heatsMax for event in system.events)
            if heatsMax == 1:
                self.headerNames = [
                    u'Event', u'Bib', u'Name', u'Note', u'Team', u'    ',
                    u'Pos', u'Bib', u'Name', u'Note', u'Team', u'Time'
                ]
            else:
                self.headerNames = [
                    u'Event', u'Bib', u'Name', u'Note', u'Team', u'H1', u'H2',
                    u'H3', u'    ', u'Pos', u'Bib', u'Name', u'Note', u'Team',
                    u'Time'
                ]
            hideCols = self.getHideCols(self.headerNames)
            self.headerNames = [
                h for c, h in enumerate(self.headerNames) if c not in hideCols
            ]

            Utils.AdjustGridSize(self.grid,
                                 rowsRequired=len(system.events),
                                 colsRequired=len(self.headerNames))
            Utils.SetGridCellBackgroundColour(self.grid, wx.WHITE)

            self.setColNames()
            state = competition.state

            for row, event in enumerate(system.events):
                writeCell = WriteCell(self.grid, row)

                writeCell(u'{}'.format(row + 1))

                riders = [state.labels.get(c, None) for c in event.composition]
                writeCell(u'\n'.join([
                    u'{}'.format(rider.bib) if rider and rider.bib else ''
                    for rider in riders
                ]))
                if getattr(model, 'resultsShowNames', True):
                    writeCell(u'\n'.join([
                        rider.full_name if rider else u'' for rider in riders
                    ]))
                writeCell(u'\n'.join([
                    competition.getRelegationsWarningsStr(
                        rider.bib, event, True) if rider else u''
                    for rider in riders
                ]))
                if getattr(model, 'resultsShowTeams', True):
                    writeCell(u'\n'.join(
                        [rider.team if rider else '' for rider in riders]))

                if heatsMax != 1:
                    for heat in six.moves.range(heatsMax):
                        if event.heatsMax != 1:
                            writeCell(u'\n'.join(event.getHeatPlaces(heat +
                                                                     1)))
                        else:
                            writeCell(u'')

                #writeCell( u' ===> ', vert=wx.ALIGN_CENTRE )
                writeCell(' '.join(['', Arrow, '']), vert=wx.ALIGN_CENTRE)

                out = [event.winner] + event.others
                riders = [state.labels.get(c, None) for c in out]
                writeCell(u'\n'.join(u'{}'.format(i + 1)
                                     for i in six.moves.range(len(riders))))
                writeCell(u'\n'.join([
                    u'{}'.format(rider.bib if rider.bib else '')
                    if rider else '' for rider in riders
                ]))
                if getattr(model, 'resultsShowNames', True):
                    writeCell(u'\n'.join([
                        rider.full_name if rider else '' for rider in riders
                    ]))
                writeCell(u'\n'.join([
                    competition.getRelegationsWarningsStr(
                        rider.bib, event, False) if rider else u''
                    for rider in riders
                ]))
                if getattr(model, 'resultsShowTeams', True):
                    writeCell(u'\n'.join(
                        [rider.team if rider else '' for rider in riders]))
                if event.winner in state.labels:
                    try:
                        value = u'%.3f' % event.starts[-1].times[1]
                    except (KeyError, IndexError, ValueError):
                        value = ''
                    writeCell(value)

            competitionTime = system.competitionTime
            self.competitionTime.SetLabel(u'{}: {}'.format(
                _('Est. Competition Time'), Utils.formatTime(competitionTime)
            ) if competitionTime else u'')

        self.grid.AutoSizeColumns(False)
        self.grid.AutoSizeRows(False)

    def commit(self):
        model = Model.model
        phase = self.getPhase()
        cn = self.communiqueNumber.GetValue()
        if cn != model.communique_number.get(phase, u''):
            model.communique_number[phase] = cn
            model.setChanged()
Exemplo n.º 14
0
class TTResults(wx.Panel):
    #----------------------------------------------------------------------
    def __init__(self, parent):
        wx.Panel.__init__(self, parent)

        self.headerNames = ['Pos', 'Bib', 'Name', 'Team', 'Time']

        self.grid = ReorderableGrid(self, style=wx.BORDER_SUNKEN)
        self.grid.DisableDragRowSize()
        self.grid.SetRowLabelSize(0)
        self.grid.CreateGrid(0, len(self.headerNames))
        self.setColNames()
        self.grid.EnableReorderRows(False)

        # Set a larger font for the table.
        # Set specialized editors for appropriate columns.
        font = GetFont()
        self.grid.SetLabelFont(font)
        for col in six.moves.range(self.grid.GetNumberCols()):
            attr = gridlib.GridCellAttr()
            attr.SetFont(font)
            if col == self.grid.GetNumberCols() - 1:
                attr.SetRenderer(gridlib.GridCellFloatRenderer(-1, 3))
                attr.SetEditor(gridlib.GridCellFloatEditor(-1, 3))
            else:
                if col in (0, 1):
                    attr.SetRenderer(gridlib.GridCellNumberRenderer())
                attr.SetReadOnly(True)
            self.grid.SetColAttr(col, attr)

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.grid, 1, flag=wx.EXPAND | wx.ALL, border=6)
        self.SetSizer(sizer)

    def setColNames(self):
        for col, headerName in enumerate(self.headerNames):
            self.grid.SetColLabelValue(col, headerName)

    def getGrid(self):
        return self.grid

    def refresh(self):
        riders = sorted(Model.model.riders, key=lambda r: r.qualifyingTime)
        starters = Model.model.competition.starters

        Utils.AdjustGridSize(self.grid, rowsRequired=len(riders))
        for row, r in enumerate(riders):
            if row < starters:
                pos = u'{}'.format(row + 1)
            else:
                pos = 'DNQ'
                for col in six.moves.range(self.grid.GetNumberCols()):
                    self.grid.SetCellBackgroundColour(row, col,
                                                      wx.Colour(200, 200, 200))
            for col, value in enumerate([
                    pos, u' {}'.format(r.bib), r.full_name, r.team,
                    '%.3f' % r.qualifyingTime
            ]):
                self.grid.SetCellValue(row, col, value)

        self.grid.AutoSizeColumns(False)
        self.grid.AutoSizeRows(False)

    def commit(self):
        pass