Exemple #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'), 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
Exemple #2
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