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'), u' {} '.format(_('Bib'))] self.maxRows = 10 fontSize = 18 self.font = wx.Font( (0,fontSize), wx.FONTFAMILY_SWISS, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL ) self.bigFont = wx.Font( (0,int(fontSize*1.30)), wx.FONTFAMILY_SWISS, wx.FONTSTYLE_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 get a Time, or press "t".'), _('Then enter the Bib number(s) and Save.') ])) ) tapExplain = wx.StaticText( self, label=_('(or press "t")') ) tapExplain.SetFont( self.font ) hbs = wx.BoxSizer( wx.HORIZONTAL ) hbs.Add( self.recordTimeButton, 0 ) hbs.Add( tapExplain, flag=wx.ALIGN_CENTRE_VERTICAL|wx.LEFT, border=20 ) self.grid = ReorderableGrid( self, style = wx.BORDER_SUNKEN ) self.grid.SetFont( self.font ) self.grid.EnableReorderRows( False ) self.grid.DisableDragColSize() self.grid.DisableDragRowSize() dc = wx.WindowDC( self.grid ) dc.SetFont( self.font ) width, height = dc.GetTextExtent(u" 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 range(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 ) saveExplain = wx.StaticText( self, label=_('(or press "s")') ) saveExplain.SetFont( self.font ) 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 "s")'))) hbsCommit = wx.BoxSizer( wx.HORIZONTAL ) hbsCommit.Add( saveExplain, flag=wx.ALIGN_CENTRE_VERTICAL|wx.RIGHT, border=20 ) hbsCommit.Add( self.commitButton, 0 ) self.vbs.Add( hbs, 0, flag=wx.ALL, border = 4 ) self.vbs.Add( self.grid, 1, flag=wx.ALL|wx.EXPAND, border = 4 ) self.vbs.Add( hbsCommit, 0, 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 range(2): for row in range(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 range(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 range(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 range(self.grid.GetNumberRows()): for column in range(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() 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.GetSizer().Layout() wx.CallAfter( self.recordTimeButton.SetFocus ) def commit( self ): pass
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