def menuExportToExcel(self, event): self.commit() iSelection = self.notebook.GetSelection() page = self.pages[iSelection] try: grid = page.getGrid() except: return try: pageTitle = self.pages[iSelection].getTitle() except: pageTitle = self.attrClassName[iSelection][2] if not self.fileName or len(self.fileName) < 4: Utils.MessageOK(self, 'You must Save before you can Export to Excel', 'Excel Write') return pageTitle = Utils.RemoveDisallowedFilenameChars( pageTitle.replace('/', '_')) xlfileName = self.fileName[:-4] + '-' + pageTitle + '.xls' dlg = wx.DirDialog(self, 'Folder to write "%s"' % os.path.basename(xlfileName), style=wx.DD_DEFAULT_STYLE, defaultPath=os.path.dirname(xlfileName)) ret = dlg.ShowModal() dName = dlg.GetPath() dlg.Destroy() if ret != wx.ID_OK: return xlfileName = os.path.join(dName, os.path.basename(xlfileName)) title = self.getTitle() wb = xlwt.Workbook() sheetName = self.attrClassName[self.notebook.GetSelection()][2] sheetCur = wb.add_sheet(sheetName) export = ExportGrid(title, grid) export.toExcelSheet(sheetCur) try: wb.save(xlfileName) webbrowser.open(xlfileName, new=2, autoraise=True) Utils.MessageOK(self, 'Excel file written to:\n\n %s' % xlfileName, 'Excel Export') except IOError: Utils.MessageOK( self, 'Cannot write "%s".\n\nCheck if this spreadsheet is open.\nIf so, close it, and try again.' % xlfileName, 'Excel File Error', iconMask=wx.ICON_ERROR)
def prepareGrid( self, page ): showLapTimes = (not Model.race) or getattr( Model.race, 'includeLapTimesInPrintout', True ) with UnstartedRaceWrapper(): if self.pageInfo[page][0] == 'Primes': exportGrid = ExportGrid( **Primes.GetGrid() ) else: exportGrid = ExportGrid() exportGrid.setResultsOneList( self.pageInfo[page][0], True, showLapTimes=showLapTimes ) return exportGrid
def prepareGrid( self, page ): exportGrid = ExportGrid() try: with UnstartedRaceWrapper(): if self.pageInfo[page][0] == 'Primes': exportGrid = ExportGrid( **Primes.GetGrid() ) else: exportGrid.setResultsOneList( self.pageInfo[page][0], True, showLapTimes=False ) except KeyError: return ExportGrid() exportGrid.title = u'\n'.join( [_('Podium Results'), u'', exportGrid.title] ) return exportGrid
def onExcel(self, event): self.commit() export = getExportGrid() xlFName = Utils.getMainWin().getFormatFilename('excel') xlFName = os.path.splitext( xlFName)[0] + '-Categories' + os.path.splitext(xlFName)[1] wb = xlsxwriter.Workbook(xlFName) sheetCur = wb.add_worksheet(_('Categories')) export.toExcelSheetXLSX(ExportGrid.getExcelFormatsXLSX(wb), sheetCur) try: wb.close() if Utils.getMainWin().launchExcelAfterPublishingResults: Utils.LaunchApplication(xlFName) Utils.MessageOK( self, u'{}:\n\n {}'.format(_('Excel file written to'), xlFName), _('Excel Write')) except IOError: Utils.MessageOK( self, u'{} "{}"\n\n{}\n{}'.format( _('Cannot write'), xlFName, _('Check if this spreadsheet is already open.'), _('If so, close it, and try again.')), _('Excel File Error'), iconMask=wx.ICON_ERROR)
def menuExportToExcel( self, event ): self.commit() iSelection = self.notebook.GetSelection() page = self.pages[iSelection] try: grid = page.getGrid() except: return try: pageTitle = self.pages[iSelection].getTitle() except: pageTitle = self.attrClassName[iSelection][2] if not self.fileName or len(self.fileName) < 4: Utils.MessageOK(self, 'You must Save before you can Export to Excel', 'Excel Write') return pageTitle = Utils.RemoveDisallowedFilenameChars( pageTitle.replace('/', '_') ) xlFName = self.fileName[:-4] + '-' + pageTitle + '.xls' dlg = wx.DirDialog( self, 'Folder to write "%s"' % os.path.basename(xlFName), style=wx.DD_DEFAULT_STYLE, defaultPath=os.path.dirname(xlFName) ) ret = dlg.ShowModal() dName = dlg.GetPath() dlg.Destroy() if ret != wx.ID_OK: return xlFName = os.path.join( dName, os.path.basename(xlFName) ) title = self.getTitle() wb = xlwt.Workbook() sheetName = pageTitle sheetName = re.sub('[+!#$%&+~`".:;|\\/?*\[\] ]+', ' ', sheetName)[:31] sheetCur = wb.add_sheet( sheetName ) export = ExportGrid( title, grid ) export.toExcelSheet( sheetCur ) try: wb.save( xlFName ) webbrowser.open( xlFName, new = 2, autoraise = True ) Utils.MessageOK(self, 'Excel file written to:\n\n %s' % xlFName, 'Excel Export') except IOError: Utils.MessageOK(self, 'Cannot write "%s".\n\nCheck if this spreadsheet is open.\nIf so, close it, and try again.' % xlFName, 'Excel File Error', iconMask=wx.ICON_ERROR )
def ToHtml( html ): for title, report in (('Results', Utils.getMainWin().rankSummary), ('Details', Utils.getMainWin().rankDetails), ): report.refresh() ExportGrid( title, report.grid).toHtml( html ) html.write( u'<br/><hr/><br/>' ) Utils.getMainWin().commentary.refresh() html.write(u'<span id="idRaceName">Commentary</span>') Utils.getMainWin().commentary.toHtml(html)
def prepareGrid(self, page): exportGrid = ExportGrid() try: with UnstartedRaceWrapper(): if self.pageInfo[page][0] == 'Primes': exportGrid = ExportGrid(**Primes.GetGrid()) else: exportGrid.setResultsOneList(self.pageInfo[page][0], True, showLapTimes=False) except KeyError: return ExportGrid() exportGrid.title = u'\n'.join( [_('Podium Results'), u'', exportGrid.title]) return exportGrid
def prepareGrid(self, page): showLapTimes = (not Model.race) or getattr( Model.race, 'includeLapTimesInPrintout', True) try: with UnstartedRaceWrapper(): if self.pageInfo[page][0] == 'Primes': exportGrid = ExportGrid(**Primes.GetGrid()) else: exportGrid = ExportGrid() exportGrid.setResultsOneList(self.pageInfo[page][0], True, showLapTimes=showLapTimes) except KeyError: return ExportGrid() return exportGrid
def ToExcel( wb ): for title, report in (('Results', Utils.getMainWin().rankSummary), ('Details', Utils.getMainWin().rankDetails), ): sheetCur = wb.add_sheet( title ) report.refresh() ExportGrid( title, report.grid).toExcelSheet( sheetCur )
def getExportGrid(): race = Model.race try: externalInfo = race.excelLink.read() except: externalInfo = {} GetTranslation = _ allZeroStarters = True with UnstartedRaceWrapper(): catMap = dict( (c.fullname, c) for c in race.getCategories(startWaveOnly=False)) catDetails = GetCategoryDetails(False, True) catDetailsMap = dict((cd['name'], cd) for cd in catDetails) title = u'\n'.join([ _('Categories'), race.title, race.scheduledStart + u' ' + _('Start on') + u' ' + Utils.formatDate(race.date) ]) colnames = [ _('Start Time'), _('Category'), _('Gender'), _('Numbers'), _('Laps'), _('Distance'), _('Starters') ] raceStart = Utils.StrToSeconds(race.scheduledStart + ':00') catData = [] for catInfo in catDetails: c = catMap.get(catInfo['name'], None) if not c: continue starters = race.catCount(c) if starters: allZeroStarters = False else: starters = '' laps = catInfo.get('laps', '') or '' raceDistance = catInfo.get('raceDistance', '') raceDistanceUnit = catInfo.get('distanceUnit', '') if raceDistance: raceDistance = '%.2f' % raceDistance if c.catType == c.CatWave: catStart = Utils.SecondsToStr(raceStart + c.getStartOffsetSecs()) elif c.catType == c.CatCustom: catStart = Utils.SecondsToStr(raceStart) else: catStart = '' catData.append([ catStart, u' - ' + c.name if c.catType == c.CatComponent else c.name, GetTranslation(catInfo.get('gender', 'Open')), c.catStr, u'{}'.format(laps), u' '.join([raceDistance, raceDistanceUnit]) if raceDistance else '', u'{}'.format(starters) ]) if allZeroStarters: colnames.remove(_('Starters')) data = [[None] * len(catData) for i in xrange(len(colnames))] for row in xrange(len(catData)): for col in xrange(len(colnames)): data[col][row] = catData[row][col] exportGrid = ExportGrid(title=title, colnames=colnames, data=data) exportGrid.leftJustifyCols = {1, 2, 3} return exportGrid
def OnPrintPage(self, page): race = Model.race if not race: return try: externalInfo = race.excelLink.read() except: externalInfo = {} GetTranslation = _ allZeroStarters = True with UnstartedRaceWrapper(): catMap = dict( (c.fullname, c) for c in race.getCategories( startWaveOnly=False ) ) catDetails = GetCategoryDetails( ignoreEmptyCategories=False, publishOnly=True ) catDetailsMap = dict( (cd['name'], cd) for cd in catDetails ) title = u'\n'.join( [_('Categories'), race.name, race.scheduledStart + u' ' + _('Start on') + u' ' + Utils.formatDate(race.date)] ) colnames = [_('Start Time'), _('Category'), _('Gender'), _('Numbers'), _('Laps'), _('Distance'), _('Starters')] raceStart = Utils.StrToSeconds( race.scheduledStart + ':00' ) catData = [] for catInfo in catDetails: c = catMap.get( catInfo['name'], None ) if not c: continue starters = race.catCount(c) if starters: allZeroStarters = False else: starters = '' laps = catInfo.get( 'laps', '' ) or '' raceDistance = catInfo.get( 'raceDistance', '' ) raceDistanceUnit = catInfo.get( 'distanceUnit', '') if raceDistance: raceDistance = '%.2f' % raceDistance if c.catType == c.CatWave: catStart = Utils.SecondsToStr( raceStart + c.getStartOffsetSecs() ) elif c.catType == c.CatCustom: catStart = Utils.SecondsToStr( raceStart ) else: catStart = '' catData.append( [ catStart, u' - ' + c.name if c.catType == c.CatComponent else c.name, GetTranslation(catInfo.get('gender', 'Open')), c.catStr, u'{}'.format(laps), u' '.join([raceDistance, raceDistanceUnit]) if raceDistance else '', u'{}'.format(starters) ]) if allZeroStarters: colnames.remove( _('Starters') ) data = [[None] * len(catData) for i in xrange(len(colnames))] for row in xrange(len(catData)): for col in xrange(len(colnames)): data[col][row] = catData[row][col] exportGrid = ExportGrid( title = title, colnames = colnames, data = data ) exportGrid.leftJustifyCols = { 1, 2, 3 } exportGrid.drawToFitDC( self.GetDC() ) return True
def OnPrintPage(self, page): exportGrid = ExportGrid( self.title, self.grid ) dc = self.GetDC() exportGrid.drawToFitDC( dc ) return True
def menuExportToHtml(self, event): self.commit() iSelection = self.notebook.GetSelection() page = self.pages[iSelection] try: grid = page.getGrid() except: return try: pageTitle = self.pages[iSelection].getTitle() except: pageTitle = self.attrClassName[iSelection][2] if not self.fileName or len(self.fileName) < 4: Utils.MessageOK(self, 'You must Save before you can Export to Html', 'Html Export') return pageTitle = Utils.RemoveDisallowedFilenameChars( pageTitle.replace('/', '_')) htmlfileName = self.fileName[:-4] + '-' + pageTitle + '.html' dlg = wx.DirDialog(self, 'Folder to write "{}"'.format( os.path.basename(htmlfileName)), style=wx.DD_DEFAULT_STYLE, defaultPath=os.path.dirname(htmlfileName)) ret = dlg.ShowModal() dName = dlg.GetPath() dlg.Destroy() if ret != wx.ID_OK: return htmlfileName = os.path.join(dName, os.path.basename(htmlfileName)) title = self.getTitle() html = StringIO.StringIO() with tag(html, 'html'): with tag(html, 'head'): with tag(html, 'title'): html.write(title.replace('\n', ' ')) with tag(html, 'meta', {'charset': 'UTF-8'}): pass for k, v in SeriesModel.model.getMetaTags(): with tag(html, 'meta', {'name': k, 'content': v}): pass with tag(html, 'style', dict(type="text/css")): html.write(''' body{ font-family: sans-serif; } #idRaceName { font-size: 200%; font-weight: bold; } #idImgHeader { box-shadow: 4px 4px 4px #888888; } .smallfont { font-size: 80%; } .bigfont { font-size: 120%; } .hidden { display: none; } table.results { font-family:"Trebuchet MS", Arial, Helvetica, sans-serif; border-collapse:collapse; } table.results td, table.results th { font-size:1em; padding:3px 7px 2px 7px; text-align: left; } table.results th { font-size:1.1em; text-align:left; padding-top:5px; padding-bottom:4px; background-color:#7FE57F; color:#000000; } table.results tr.odd { color:#000000; background-color:#EAF2D3; } table.results tr:hover { color:#000000; background-color:#FFFFCC; } table.results tr.odd:hover { color:#000000; background-color:#FFFFCC; } table.results td { border-top:1px solid #98bf21; } table.results td.noborder { border-top:0px solid #98bf21; } table.results td.rAlign, table.results th.rAlign { text-align:right; } table.results tr td.fastest{ color:#000000; background-color:#80FF80; } @media print { .noprint { display: none; } }''') with tag(html, 'body'): ExportGrid(title, grid).toHtml(html) html = html.getvalue() try: with open(htmlfileName, 'wb') as fp: fp.write(html) webbrowser.open(htmlfileName, new=2, autoraise=True) Utils.MessageOK(self, 'Html file written to:\n\n %s' % 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)
def refresh( self ): self.category = None self.isEmpty = True self.iLastLap = 0 self.rcInterp = set() # Set of row/col coordinates of interpolated numbers. self.rcNumTime = set() self.search.SelectAll() CloseFinishTime = 0.07 self.closeFinishBibs = defaultdict( list ) race = Model.race if not race: self.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 sortLap = getattr( race, 'sortLap', None ) sortLabel = getattr( race, 'sortLabel', None ) if race.isTimeTrial: def getSortTime( rr ): try: return rr.firstTime + rr._lastTimeOrig except: return 0 else: def getSortTime( rr ): try: return rr._lastTimeOrig except: return 0 results = sorted( (rr for rr in GetResults(category) if rr.status==Model.Rider.Finisher and rr.lapTimes and getSortTime(rr) > 0), key = getSortTime ) for i in xrange(1, len(results)): if results[i]._lastTimeOrig - results[i-1]._lastTimeOrig <= CloseFinishTime: self.closeFinishBibs[results[i-1].num].append( results[i].num ) self.closeFinishBibs[results[i].num].append( results[i-1].num ) labelLastX, labelLastY = self.labelGrid.GetViewStart() lapLastX, lapLastY = self.lapGrid.GetViewStart() exportGrid = ExportGrid() exportGrid.setResultsOneList( category, self.showRiderData, showLapsFrequency = 1 ) if not exportGrid.colnames: self.clearGrid() return # Fix the speed column. speedUnit = None iSpeedCol = None try: iSpeedCol = (i for i, c in enumerate(exportGrid.colnames) if c == _('Speed')).next() except StopIteration: pass if iSpeedCol is not None: for r, d in enumerate(exportGrid.data[iSpeedCol]): d = d.strip() if not d: continue dSplit = d.split() if not speedUnit and len(dSplit) > 1: exportGrid.colnames[iSpeedCol] = speedUnit = dSplit[1] exportGrid.data[iSpeedCol][r] = dSplit[0] if exportGrid.data[iSpeedCol][r] == '"': exportGrid.data[iSpeedCol][r] += ' ' colnames = exportGrid.colnames data = exportGrid.data sortCol = None if sortLap: race.sortLabel = sortLabel = None for i, name in enumerate(colnames): if name.startswith(_('Lap')) and int(name.split()[1]) == sortLap: sortCol = i break elif sortLabel: race.sortLap = sortLap = None if sortLabel not in {_('Pos'), _('Gap'), _('Time'), _('mph'), _('km/h')}: for i, name in enumerate(colnames): if name == sortLabel: sortCol = i break if sortCol is None: race.sortLabel = race.sortLap = sortLabel = sortLap = None results = GetResults( category ) hasSpeeds = False for result in results: if getattr(result, 'lapSpeeds', None) or getattr(result, 'raceSpeeds', None): hasSpeeds = True break if not hasSpeeds: self.showLapSpeedsRadio.Enable( False ) self.showRaceSpeedsRadio.Enable( False ) if self.selectDisplay > Results.DisplayRaceTimes: self.selectDisplay = Results.DisplayRaceTimes self.showRaceTimesRadio.SetValue( True ) else: self.showLapSpeedsRadio.Enable( True ) self.showRaceSpeedsRadio.Enable( True ) for r in [self.showLapTimesRadio, self.showRaceTimesRadio, self.showLapSpeedsRadio, self.showRaceSpeedsRadio]: if r.GetValue(): r.SetFont( self.boldFont ) else: r.SetFont( wx.NullFont ) self.hbs.RecalcSizes() self.hbs.Layout() # Find the fastest lap time. self.fastestLapRC, fastestLapSpeed, fastestLapTime = None, 0.0, sys.float_info.max for r, result in enumerate(results): if getattr(result, 'lapSpeeds', None): # Use speeds if available. for c, s in enumerate(result.lapSpeeds): if s > fastestLapSpeed: fastestLapSpeed = s self.fastestLapRC = (r, c) elif result.lapTimes: # Else, use times. for c, t in enumerate(result.lapTimes): if t < fastestLapTime: fastestLapTime = t self.fastestLapRC = (r, c) highPrecision = Model.highPrecisionTimes() try: firstLapCol = (i for i, name in enumerate(colnames) if name.startswith(_('Lap'))).next() except StopIteration: firstLapCol = len(colnames) # Convert to race times, lap speeds or race speeds as required. ''' DisplayLapTimes = 0 DisplayRaceTimes = 1 DisplayLapSpeeds = 2 DisplayRaceSpeeds = 3 ''' if self.selectDisplay == Results.DisplayRaceTimes: for r, result in enumerate(results): for i, t in enumerate(result.raceTimes[1:]): try: data[i+firstLapCol][r] = Utils.formatTimeCompressed(t, highPrecision) except IndexError: pass elif self.selectDisplay == Results.DisplayLapSpeeds: for r, result in enumerate(results): if getattr(result, 'lapSpeeds', None): for i, s in enumerate(result.lapSpeeds): try: data[i+firstLapCol][r] = u'{:.2f}'.format(s) except IndexError: pass elif self.selectDisplay == Results.DisplayRaceSpeeds: for r, result in enumerate(results): if getattr(result, 'raceSpeeds', None): for i, s in enumerate(result.raceSpeeds): try: data[i+firstLapCol][r] = u'{:.2f}'.format(s) except IndexError: pass # Sort by the given lap, if there is one. # Also, add a position for the lap itself. if sortCol is not None: maxVal = 1000.0*24.0*60.0*60.0 if sortLap: if self.selectDisplay in [Results.DisplayLapTimes, Results.DisplayRaceTimes]: getFunc = Utils.StrToSeconds else: getFunc = lambda x: -float(x) else: if colnames[sortCol] in [_('Start'), _('Finish'), _('Time')]: getFunc = Utils.StrToSeconds elif colnames[sortCol] in [_('mph'), _('km')]: getFunc = lambda x: -float(x) if x else 0.0 elif colnames[sortCol] == _('Factor'): getFunc = lambda x: float(x) if x else maxVal elif colnames[sortCol] in [_('Pos'), _('Bib')]: getFunc = lambda x: int(x) if x and unicode(x).isdigit() else maxVal else: getFunc = lambda x: u'{}'.format(x) maxVal = '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~' sortPairs = [] for r, result in enumerate(results): try: k = (getFunc(data[sortCol][r]), r) except Exception as e: k = (maxVal, r) sortPairs.append( (k, r) ) sortPairs.sort() for c in xrange(len(data)): col = data[c] data[c] = [col[i] if i < len(col) else u'' for k, i in sortPairs] if colnames[sortCol] != _('Bib'): for r in xrange(len(data[sortCol])): if data[sortCol][r]: data[sortCol][r] = u'{} [{}: {}]'.format(data[sortCol][r], r+1, data[1][r]) # Highlight the sorted column. if sortLap: colnames = [] for name in exportGrid.colnames: try: if int(name.split()[1]) == sortLap: name = u'<{}>\n{}'.format(name, [_('by Lap Time'), _('by Race Time'), _('by Lap Speed'), _('by Race Speed')][self.selectDisplay]) except: pass colnames.append( name ) elif sortLabel: colnames = [] for name in exportGrid.colnames: if name == sortLabel: name = u'<{}>'.format(name) colnames.append( name ) else: colnames = exportGrid.colnames try: iLabelMax = (i for i, name in enumerate(colnames) if name.startswith(_('Lap')) or name.startswith('<' + _('Lap'))).next() except StopIteration: iLabelMax = len(colnames) colnamesLabels = colnames[:iLabelMax] dataLabels = data[:iLabelMax] colnameLaps = colnames[iLabelMax:] dataLaps = data[iLabelMax:] self.labelGrid.Set( data = dataLabels, colnames = colnamesLabels ) self.labelGrid.SetLeftAlignCols( exportGrid.leftJustifyCols ) self.labelGrid.AutoSizeColumns( True ) self.labelGrid.Reset() try: iUCICodeCol = colnamesLabels.index( _('UCICode') ) self.labelGrid.SetColRenderer( iUCICodeCol, IOCCodeRenderer() ) except ValueError: pass try: iNatCodeCol = colnamesLabels.index( _('NatCode') ) self.labelGrid.SetColRenderer( iNatCodeCol, IOCCodeRenderer() ) except ValueError: pass self.lapGrid.Set( data = dataLaps, colnames = colnameLaps ) self.lapGrid.Reset() self.lapGrid.AutoSizeColumns( self.lapGrid.GetNumberCols() < 100 ) self.isEmpty = False # Find interpolated entries. with Model.LockRace() as race: numTimeInfo = race.numTimeInfo riders = race.riders for r in xrange(self.lapGrid.GetNumberRows()): try: rider = riders[int(self.labelGrid.GetCellValue(r, 1))] except: continue try: entries = rider.interpolate() except (ValueError, IndexError): continue if not entries: continue for c in xrange(self.lapGrid.GetNumberCols()): if not self.lapGrid.GetCellValue(r, c): break try: if entries[c+1].interp: self.rcInterp.add( (r, c) ) elif numTimeInfo.getInfo(entries[c+1].num, entries[c+1].t) is not None: self.rcNumTime.add( (r, c) ) elif c > self.iLastLap: self.iLastLap = c except IndexError: pass self.labelGrid.Scroll( labelLastX, labelLastY ) self.lapGrid.Scroll( lapLastX, lapLastY ) self.showNumSelect() if self.firstDraw: self.firstDraw = False self.splitter.SetSashPosition( 400 ) # Fix the grids' scrollbars. self.labelGrid.FitInside() self.lapGrid.FitInside()
def prepareGrid( self, page ): exportGrid = ExportGrid() with UnstartedRaceWrapper(): exportGrid.setResultsOneList( self.pageInfo[page][0], True, showLapTimes=False ) exportGrid.title = u'\n'.join( [_('Podium Results'), u'', exportGrid.title] ) return exportGrid
def prepareGrid( self, page ): exportGrid = ExportGrid() showLapTimes = (not Model.race) or getattr( Model.race, 'includeLapTimesInPrintout', True ) exportGrid.setResultsOneList( self.pageInfo[page][0], True, showLapTimes = showLapTimes ) return exportGrid
def menuExportToHtml( self, event ): self.commit() iSelection = self.notebook.GetSelection() page = self.pages[iSelection] grid = None image = None try: grid = page.getGrid() except Exception as e: pass if not grid: try: image = page.getImage() except Exception as e: pass if not (grid or image): return try: pageTitle = self.pages[iSelection].getTitle() except: pageTitle = self.attrClassName[iSelection][2] if not self.fileName or len(self.fileName) < 4: Utils.MessageOK(self, u'You must Save before you can Export to Html', u'Excel Export') return pageTitle = Utils.RemoveDisallowedFilenameChars( pageTitle.replace(u'/', u'_') ) htmlFName = self.fileName[:-4] + '-' + pageTitle + '.html' dlg = wx.DirDialog( self, u'Folder to write "%s"' % os.path.basename(htmlFName), style=wx.DD_DEFAULT_STYLE, defaultPath=os.path.dirname(htmlFName) ) ret = dlg.ShowModal() dName = dlg.GetPath() dlg.Destroy() if ret != wx.ID_OK: return htmlFName = os.path.join( dName, os.path.basename(htmlFName) ) title = self.getTitle() htmlStream = StringIO() html = codecs.getwriter('utf8')( htmlStream ) with tag(html, 'html'): with tag(html, 'head'): with tag(html, 'title'): html.write( title.replace(u'\n', u' ') ) with tag(html, 'meta', dict(charset="UTF-8", author="Edward Sitarski", copyright="Edward Sitarski, 2013", generator="SprintMgr")): pass with tag(html, 'style', dict( type="text/css")): html.write( ''' body{ font-family: sans-serif; } #idRaceName { font-size: 200%; font-weight: bold; } #idImgHeader { box-shadow: 4px 4px 4px #888888; } .smallfont { font-size: 80%; } .bigfont { font-size: 120%; } .hidden { display: none; } table.results { font-family:"Trebuchet MS", Arial, Helvetica, sans-serif; border-collapse:collapse; } table.results td, table.results th { font-size:1em; padding:3px 7px 2px 7px; text-align: left; } table.results th { font-size:1.1em; text-align:left; padding-top:5px; padding-bottom:4px; background-color:#7FE57F; color:#000000; } table.results tr.odd { color:#000000; background-color:#EAF2D3; } table.results tr:hover { color:#000000; background-color:#FFFFCC; } table.results tr.odd:hover { color:#000000; background-color:#FFFFCC; } table.results td { border-top:1px solid #98bf21; } table.results td.noborder { border-top:0px solid #98bf21; } table.results td.rAlign, table.results th.rAlign { text-align:right; } table.results tr td.fastest{ color:#000000; background-color:#80FF80; } @media print { .noprint { display: none; } }''' ) with tag(html, 'body'): if grid: ExportGrid( title, grid ).toHtml(html) elif image: pngFName = os.path.join( dName, '{}.png'.format(uuid.uuid4()) ) image.SaveFile( pngFName, wx.BITMAP_TYPE_PNG ) with open(pngFName, 'rb') as fp: data = base64.b64encode( fp.read() ) os.remove( pngFName ) writeHtmlHeader( html, title ) html.write( '<img id="idResultsSummary" src="data:image/png;base64,%s" />' % data ) html = htmlStream.getvalue() try: with open(htmlFName, 'wb') as fp: fp.write( html ) webbrowser.open( htmlFName, new = 2, autoraise = True ) Utils.MessageOK(self, u'Html file written to:\n\n %s' % htmlFName, 'Html Write') except IOError: Utils.MessageOK(self, u'Cannot write "%s".\n\nCheck if this file is open.\nIf so, close it, and try again.' % htmlFName, u'Html File Error', iconMask=wx.ICON_ERROR )
def OnPrintPage(self, page): exportGrid = ExportGrid(self.title, self.grid) dc = self.GetDC() exportGrid.drawToFitDC(dc) return True
def refresh(self): self.category = None self.isEmpty = True self.iLastLap = 0 self.rcInterp = set( ) # Set of row/col coordinates of interpolated numbers. self.rcNumTime = set() self.search.SelectAll() CloseFinishTime = 0.07 self.closeFinishBibs = defaultdict(list) race = Model.race if not race: self.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 sortLap = getattr(race, 'sortLap', None) sortLabel = getattr(race, 'sortLabel', None) if race.isTimeTrial: def getSortTime(rr): try: return rr.firstTime + rr._lastTimeOrig except: return 0 else: def getSortTime(rr): try: return rr._lastTimeOrig except: return 0 results = sorted((rr for rr in GetResults(category) if rr.status == Model.Rider.Finisher and rr.lapTimes and getSortTime(rr) > 0), key=getSortTime) for i in range(1, len(results)): if results[i]._lastTimeOrig - results[ i - 1]._lastTimeOrig <= CloseFinishTime: self.closeFinishBibs[results[i - 1].num].append(results[i].num) self.closeFinishBibs[results[i].num].append(results[i - 1].num) labelLastX, labelLastY = self.labelGrid.GetViewStart() lapLastX, lapLastY = self.lapGrid.GetViewStart() exportGrid = ExportGrid() exportGrid.setResultsOneList(category, self.showRiderData, showLapsFrequency=1) if not exportGrid.colnames: self.clearGrid() return # Fix the speed column. speedUnit = None iSpeedCol = None try: iSpeedCol = next(i for i, c in enumerate(exportGrid.colnames) if c == _('Speed')) except StopIteration: pass if iSpeedCol is not None: for r, d in enumerate(exportGrid.data[iSpeedCol]): d = d.strip() if not d: continue dSplit = d.split() if not speedUnit and len(dSplit) > 1: exportGrid.colnames[iSpeedCol] = speedUnit = dSplit[1] exportGrid.data[iSpeedCol][r] = dSplit[0] if exportGrid.data[iSpeedCol][r] == '"': exportGrid.data[iSpeedCol][r] += ' ' colnames = exportGrid.colnames data = exportGrid.data sortCol = None if sortLap: race.sortLabel = sortLabel = None for i, name in enumerate(colnames): if name.startswith(_('Lap')) and int( name.split()[1]) == sortLap: sortCol = i break elif sortLabel: race.sortLap = sortLap = None if sortLabel not in { _('Pos'), _('Gap'), _('Time'), _('mph'), _('km/h') }: for i, name in enumerate(colnames): if name == sortLabel: sortCol = i break if sortCol is None: race.sortLabel = race.sortLap = sortLabel = sortLap = None results = GetResults(category) hasSpeeds = False for result in results: if getattr(result, 'lapSpeeds', None) or getattr( result, 'raceSpeeds', None): hasSpeeds = True break if not hasSpeeds: self.showLapSpeedsRadio.Enable(False) self.showRaceSpeedsRadio.Enable(False) if self.selectDisplay > Results.DisplayRaceTimes: self.selectDisplay = Results.DisplayRaceTimes self.showRaceTimesRadio.SetValue(True) else: self.showLapSpeedsRadio.Enable(True) self.showRaceSpeedsRadio.Enable(True) for r in [ self.showLapTimesRadio, self.showRaceTimesRadio, self.showLapSpeedsRadio, self.showRaceSpeedsRadio ]: if r.GetValue(): r.SetFont(self.boldFont) else: r.SetFont(wx.NullFont) self.hbs.RecalcSizes() self.hbs.Layout() # Find the fastest lap time. self.fastestLapRC, fastestLapSpeed, fastestLapTime = None, 0.0, sys.float_info.max for r, result in enumerate(results): if getattr(result, 'lapSpeeds', None): # Use speeds if available. for c, s in enumerate(result.lapSpeeds): if s > fastestLapSpeed: fastestLapSpeed = s self.fastestLapRC = (r, c) elif result.lapTimes: # Else, use times. for c, t in enumerate(result.lapTimes): if t < fastestLapTime: fastestLapTime = t self.fastestLapRC = (r, c) highPrecision = Model.highPrecisionTimes() try: firstLapCol = next(i for i, name in enumerate(colnames) if name.startswith(_('Lap'))) except StopIteration: firstLapCol = len(colnames) # Convert to race times, lap speeds or race speeds as required. ''' DisplayLapTimes = 0 DisplayRaceTimes = 1 DisplayLapSpeeds = 2 DisplayRaceSpeeds = 3 ''' if self.selectDisplay == Results.DisplayRaceTimes: for r, result in enumerate(results): for i, t in enumerate(result.raceTimes[1:]): try: data[i + firstLapCol][r] = Utils.formatTimeCompressed( t, highPrecision) except IndexError: pass elif self.selectDisplay == Results.DisplayLapSpeeds: for r, result in enumerate(results): if getattr(result, 'lapSpeeds', None): for i, s in enumerate(result.lapSpeeds): try: data[i + firstLapCol][r] = u'{:.2f}'.format(s) except IndexError: pass elif self.selectDisplay == Results.DisplayRaceSpeeds: for r, result in enumerate(results): if getattr(result, 'raceSpeeds', None): for i, s in enumerate(result.raceSpeeds): try: data[i + firstLapCol][r] = u'{:.2f}'.format(s) except IndexError: pass # Sort by the given lap, if there is one. # Also, add a position for the lap itself. if sortCol is not None: maxVal = 1000.0 * 24.0 * 60.0 * 60.0 if sortLap: if self.selectDisplay in [ Results.DisplayLapTimes, Results.DisplayRaceTimes ]: getFunc = Utils.StrToSeconds else: getFunc = lambda x: -float(x) else: if colnames[sortCol] in [_('Start'), _('Finish'), _('Time')]: getFunc = Utils.StrToSeconds elif colnames[sortCol] in [_('mph'), _('km')]: getFunc = lambda x: -float(x) if x else 0.0 elif colnames[sortCol] == _('Factor'): getFunc = lambda x: float(x) if x else maxVal elif colnames[sortCol] in [_('Pos'), _('Bib')]: getFunc = lambda x: int(x) if x and six.text_type( x).isdigit() else maxVal else: getFunc = lambda x: u'{}'.format(x) maxVal = '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~' sortPairs = [] for r, result in enumerate(results): try: k = (getFunc(data[sortCol][r]), r) except Exception as e: k = (maxVal, r) sortPairs.append((k, r)) sortPairs.sort() for c in range(len(data)): col = data[c] data[c] = [ col[i] if i < len(col) else u'' for k, i in sortPairs ] if colnames[sortCol] != _('Bib'): for r in range(len(data[sortCol])): if data[sortCol][r]: data[sortCol][r] = u'{} [{}: {}]'.format( data[sortCol][r], r + 1, data[1][r]) # Highlight the sorted column. if sortLap: colnames = [] for name in exportGrid.colnames: try: if int(name.split()[1]) == sortLap: name = u'<{}>\n{}'.format(name, [ _('by Lap Time'), _('by Race Time'), _('by Lap Speed'), _('by Race Speed') ][self.selectDisplay]) except: pass colnames.append(name) elif sortLabel: colnames = [] for name in exportGrid.colnames: if name == sortLabel: name = u'<{}>'.format(name) colnames.append(name) else: colnames = exportGrid.colnames try: iLabelMax = next( i for i, name in enumerate(colnames) if name.startswith(_('Lap')) or name.startswith('<' + _('Lap'))) except StopIteration: iLabelMax = len(colnames) colnamesLabels = colnames[:iLabelMax] dataLabels = data[:iLabelMax] colnameLaps = colnames[iLabelMax:] dataLaps = data[iLabelMax:] self.labelGrid.Set(data=dataLabels, colnames=colnamesLabels) self.labelGrid.SetLeftAlignCols(exportGrid.leftJustifyCols) self.labelGrid.AutoSizeColumns(True) self.labelGrid.Reset() try: iUCICodeCol = colnamesLabels.index(_('UCICode')) self.labelGrid.SetColRenderer(iUCICodeCol, IOCCodeRenderer()) except ValueError: pass try: iNatCodeCol = colnamesLabels.index(_('NatCode')) self.labelGrid.SetColRenderer(iNatCodeCol, IOCCodeRenderer()) except ValueError: pass self.lapGrid.Set(data=dataLaps, colnames=colnameLaps) self.lapGrid.Reset() self.lapGrid.AutoSizeColumns(self.lapGrid.GetNumberCols() < 100) self.isEmpty = False # Find interpolated entries. with Model.LockRace() as race: numTimeInfo = race.numTimeInfo riders = race.riders for r in range(self.lapGrid.GetNumberRows()): try: rider = riders[int(self.labelGrid.GetCellValue(r, 1))] except: continue try: entries = rider.interpolate() except (ValueError, IndexError): continue if not entries: continue for c in range(self.lapGrid.GetNumberCols()): if not self.lapGrid.GetCellValue(r, c): break try: if entries[c + 1].interp: self.rcInterp.add((r, c)) elif numTimeInfo.getInfo(entries[c + 1].num, entries[c + 1].t) is not None: self.rcNumTime.add((r, c)) elif c > self.iLastLap: self.iLastLap = c except IndexError: pass self.labelGrid.Scroll(labelLastX, labelLastY) self.lapGrid.Scroll(lapLastX, lapLastY) self.showNumSelect() if self.firstDraw: self.firstDraw = False self.splitter.SetSashPosition(400) # Fix the grids' scrollbars. self.labelGrid.FitInside() self.lapGrid.FitInside()