cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync# -*- coding: utf-8 -*-
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncTest Manager WUI - Graph Wizard
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncCopyright (C) 2012-2014 Oracle Corporation
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncThis file is part of VirtualBox Open Source Edition (OSE), as
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncavailable from http://www.virtualbox.org. This file is free software;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncyou can redistribute it and/or modify it under the terms of the GNU
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncGeneral Public License (GPL) as published by the Free Software
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncFoundation, in version 2 as it comes in the "COPYING" file of the
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncVirtualBox OSE distribution. VirtualBox OSE is distributed in the
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsynchope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncThe contents of this file may alternatively be used under the terms
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncof the Common Development and Distribution License Version 1.0
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync(CDDL) only, as it comes in the "COPYING.CDDL" file of the
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncVirtualBox OSE distribution, in which case the provisions of the
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncCDDL are applicable instead of those of the GPL.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncYou may elect to license modified versions of this file under the
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncterms and conditions of either the GPL or the CDDL or both.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync# Python imports.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync# Validation Kit imports.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncfrom testmanager.webui.wuihlpgraph import WuiHlpLineGraphErrorbarY, WuiHlpGraphDataTableEx;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncfrom testmanager.webui.wuireport import WuiReportBase;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync """Construct a graph for analyzing test results (values) across builds and testboxes."""
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ## @name Series name parts.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync def __init__(self, oModel, dParams, fSubReport = False, fnDPrint = None, oDisp = None):
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync WuiReportBase.__init__(self, oModel, dParams, fSubReport = fSubReport, fnDPrint = fnDPrint, oDisp = oDisp);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # Select graph implementation.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if dParams[WuiMain.ksParamGraphWizImpl] == 'charts':
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync from testmanager.webui.wuihlpgraphgooglechart import WuiHlpLineGraphErrorbarY as MyGraph;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync elif dParams[WuiMain.ksParamGraphWizImpl] == 'matplotlib':
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync from testmanager.webui.wuihlpgraphmatplotlib import WuiHlpLineGraphErrorbarY as MyGraph;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync """ Figures out the method (bitmask) to use when naming series. """
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # Start with all and drop unnecessary specs one-by-one.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if [oSrs.idTestBox for oSrs in aoSeries].count(aoSeries[0].idTestBox) == len(aoSeries):
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if [oSrs.idBuildCategory for oSrs in aoSeries].count(aoSeries[0].idBuildCategory) == len(aoSeries):
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if [oSrs.oBuildCategory.sProduct for oSrs in aoSeries].count(aoSeries[0].oBuildCategory.sProduct) == len(aoSeries):
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if [oSrs.oBuildCategory.sBranch for oSrs in aoSeries].count(aoSeries[0].oBuildCategory.sBranch) == len(aoSeries):
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if [oSrs.oBuildCategory.sType for oSrs in aoSeries].count(aoSeries[0].oBuildCategory.sType) == len(aoSeries):
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # Complicated.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync for _, aoSeriesPerTestBox in daTestBoxes.iteritems():
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync asOsArches = aoSeriesPerTestBox[0].oBuildCategory.asOsArches;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if aoSeriesPerTestBox[i].oBuildCategory.asOsArches != asOsArches:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if [oSrs.idTestCase for oSrs in aoSeries].count(aoSeries[0].idTestCase) == len(aoSeries):
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if [oSrs.idTestCaseArgs for oSrs in aoSeries].count(aoSeries[0].idTestCaseArgs) == len(aoSeries):
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync """ Creates a series name from bits (kfSeriesName_xxx). """
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sName += ' & '.join(oSeries.oBuildCategory.asOsArches);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sName += oSeries.oTestCase.sName + ':#' + str(oSeries.idTestCaseArgs);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync def _calcGraphName(self, oSeries, fSeriesName, sSampleName):
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync """ Constructs a name for the graph. """
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync fGraphName = ~fSeriesName & ( WuiGraphWiz.kfSeriesName_TestBox
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sName = self._getSeriesNameFromBits(oSeries, fGraphName);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync """ Constructs a name for a sample source (collection). """
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync elif oCollection.sType == self._oModel.ksTypeElapsed:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync elif oCollection.sType == self._oModel.ksTypeResult:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return 'Invalid collection type: "%s"' % (oCollection.sType,);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sTestName = ', '.join(oCollection.asTests if len(oCollection.asTests[0]) else oCollection.asTests[1:]);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # Use the testcase name if there is only one for all series.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sTestName = oCollection.aoSeries[0].oTestCase.sName;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Splits the data series (ReportGraphModel.DataSeries) into one or more graphs.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Returns an array of data series arrays.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # Must be at least two series for something to be splittable.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # Split on unit.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # Sort the per-unit series since the build category was only sorted by ID.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync """ __cmp__ like function. """
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync iCmp = utils.stricmp(oSelf.oBuildCategory.sProduct, oOther.oBuildCategory.sProduct);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync iCmp = utils.stricmp(oSelf.oBuildCategory.sBranch, oOther.oBuildCategory.sBranch);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync iCmp = utils.stricmp(oSelf.oBuildCategory.sType, oOther.oBuildCategory.sType);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync iCmp = utils.stricmp(oSelf.oTestBox.sName, oOther.oTestBox.sName);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync dUnitSeries[iUnit] = sorted(dUnitSeries[iUnit], key = functools.cmp_to_key(mycmp));
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # Split the per-unit series up if necessary.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync cMaxPerGraph = self._dParams[WuiMain.ksParamGraphWizMaxPerGraph];
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Configures oGraph according to user parameters and other config settings.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Returns oGraph.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync oGraph.setWidth(self._dParams[WuiMain.ksParamGraphWizWidth])
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync oGraph.setHeight(self._dParams[WuiMain.ksParamGraphWizHeight])
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync oGraph.setDpi(self._dParams[WuiMain.ksParamGraphWizDpi])
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync oGraph.setErrorBarY(self._dParams[WuiMain.ksParamGraphWizErrorBarY]);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync oGraph.setFontSize(self._dParams[WuiMain.ksParamGraphWizFontSize]);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync oGraph.setXkcdStyle(self._dParams[WuiMain.ksParamGraphWizXkcdStyle]);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Generates the HTML for the interactive form.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Returns (sTopOfForm, sEndOfForm)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # The top of the form.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sTop = '<form action="#" method="get" id="graphwiz-form">\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ' <input type="hidden" name="%s" value="%s"/>\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ' <input type="hidden" name="%s" value="%u"/>\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync % ( WuiMain.ksParamAction, WuiMain.ksActionGraphWiz,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync WuiMain.ksParamGraphWizSrcTestSetId, self._dParams[WuiMain.ksParamGraphWizSrcTestSetId],
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ' window.onresize = function(){ return graphwizOnResizeRecalcWidth("graphwiz-nav", "%s"); }\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ' window.onload = function(){ return graphwizOnLoadRememberWidth("graphwiz-nav"); }\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ' </script>\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # Top: First row.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sNow = self._dParams[WuiMain.ksParamEffectiveDate];
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ' <input type="text" name="%s" id="%s" value="%s" class="graphwiz-time-input"/>\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync WuiMain.ksParamEffectiveDate, WuiMain.ksParamEffectiveDate, sNow, );
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sTop += ' <input type="hidden" name="%s" value="%u"/>\n' % ( WuiMain.ksParamReportPeriods, 1, );
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ' <input type="text" name="%s" id="%s" value="%s" class="graphwiz-period-input"/>\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync WuiMain.ksParamReportPeriodInHours, WuiMain.ksParamReportPeriodInHours,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync utils.formatIntervalHours(self._dParams[WuiMain.ksParamReportPeriodInHours]) );
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # Graph options top row.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # graph type.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ' <select name="%s" id="%s">\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync % ( WuiMain.ksParamGraphWizImpl, WuiMain.ksParamGraphWizImpl, WuiMain.ksParamGraphWizImpl, );
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync for (sImpl, sDesc) in WuiMain.kaasGraphWizImplCombo:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync % (sImpl, ' selected' if sImpl == self._dParams[WuiMain.ksParamGraphWizImpl] else '', sDesc);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # graph size.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ' <input type="text" name="%s" id="%s" value="%s" class="graphwiz-pixel-input"> x\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ' <input type="text" name="%s" id="%s" value="%s" class="graphwiz-pixel-input">\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ' <label for="%s">Dpi:</label>'\
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ' <input type="text" name="%s" id="%s" value="%s" class="graphwiz-dpi-input">\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ' <button type="button" onclick="%s">Defaults</button>\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync WuiMain.ksParamGraphWizWidth, WuiMain.ksParamGraphWizWidth, self._dParams[WuiMain.ksParamGraphWizWidth],
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync WuiMain.ksParamGraphWizHeight, WuiMain.ksParamGraphWizHeight, self._dParams[WuiMain.ksParamGraphWizHeight],
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync WuiMain.ksParamGraphWizDpi, WuiMain.ksParamGraphWizDpi, self._dParams[WuiMain.ksParamGraphWizDpi],
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync webutils.escapeAttr('return graphwizSetDefaultSizeValues("graphwiz-nav", "%s", "%s", "%s");'
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync % ( WuiMain.ksParamGraphWizWidth, WuiMain.ksParamGraphWizHeight,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # Top: Second row.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sFormButton = '<button type="submit">Refresh</button>\n';
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sTop += ' <div id="graphwiz-top-submit">' + sFormButton + '</div>\n';
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sTop += ' <input type="checkbox" name="%s" id="%s" value="1"%s/>\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ' <label for="%s">Tabular data</label>\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync % ( WuiMain.ksParamGraphWizTabular, WuiMain.ksParamGraphWizTabular,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ' checked' if self._dParams[WuiMain.ksParamGraphWizTabular] else '',
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sTop += ' <input type="checkbox" name="%s" id="%s" value="1"%s/>\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ' <label for="%s">xkcd-style</label>\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync % ( WuiMain.ksParamGraphWizXkcdStyle, WuiMain.ksParamGraphWizXkcdStyle,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ' checked' if self._dParams[WuiMain.ksParamGraphWizXkcdStyle] else '',
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync elif self._dParams[WuiMain.ksParamGraphWizXkcdStyle]:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sTop += ' <input type="hidden" name="%s" id="%s" value="1"/>\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync % ( WuiMain.ksParamGraphWizXkcdStyle, WuiMain.ksParamGraphWizXkcdStyle, );
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if not hasattr(self.oGraphClass, 'kfNoErrorBarsSupport'):
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sTop += ' <input type="checkbox" name="%s" id="%s" value="1"%s title="%s"/>\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ' <label for="%s">Error bars,</label>\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ' <label for="%s">max: </label>\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ' <input type="text" name="%s" id="%s" value="%s" class="graphwiz-maxerrorbar-input" title="%s"/>\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync % ( WuiMain.ksParamGraphWizErrorBarY, WuiMain.ksParamGraphWizErrorBarY,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ' checked' if self._dParams[WuiMain.ksParamGraphWizErrorBarY] else '',
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync 'Error bars shows some of the max and min results on the Y-axis.',
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync WuiMain.ksParamGraphWizMaxErrorBarY, WuiMain.ksParamGraphWizMaxErrorBarY,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self._dParams[WuiMain.ksParamGraphWizMaxErrorBarY],
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync 'Maximum number of Y-axis error bar per graph. (Too many makes it unreadable.)'
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if self._dParams[WuiMain.ksParamGraphWizErrorBarY]:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sTop += '<input type="hidden" name="%s" id="%s" value="1">\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync % ( WuiMain.ksParamGraphWizErrorBarY, WuiMain.ksParamGraphWizErrorBarY, );
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sTop += '<input type="hidden" name="%s" id="%s" value="%u">\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync % ( WuiMain.ksParamGraphWizMaxErrorBarY, WuiMain.ksParamGraphWizMaxErrorBarY,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self._dParams[WuiMain.ksParamGraphWizMaxErrorBarY], );
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ' <input type="text" name="%s" id="%s" value="%s" class="graphwiz-fontsize-input"/>\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync WuiMain.ksParamGraphWizFontSize, WuiMain.ksParamGraphWizFontSize,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sTop += ' <label for="%s">Data series: </label>\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ' <input type="text" name="%s" id="%s" value="%s" class="graphwiz-maxpergraph-input" title="%s"/>\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync WuiMain.ksParamGraphWizMaxPerGraph, WuiMain.ksParamGraphWizMaxPerGraph,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync 'Max data series per graph.' );
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # The end of the page selection.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # Testbox selection
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync aidTestBoxes = list(self._dParams[WuiMain.ksParamGraphWizTestBoxIds]);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sEnd += ' <div id="graphwiz-testboxes" class="graphwiz-end-selection-group">\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ' <h3>TestBox Selection:</h3>\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ' <ol class="tmgraph-testboxes">\n';
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # Get a list of eligible testboxes from the DB.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync for oTestBox in self._oModel.getEligibleTestBoxes():
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sEnd += ' <li><input type="checkbox" name="%s" value="%s" id="gw-tb-%u"%s/>' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync '<label for="gw-tb-%u">%s</label></li>\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync % ( WuiMain.ksParamGraphWizTestBoxIds, oTestBox.idTestBox, oTestBox.idTestBox, sChecked,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # List testboxes that have been checked in a different period or something.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync oTestBox = self._oModel.oCache.getTestBox(idTestBox);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sEnd += ' <li><input type="checkbox" name="%s" value="%s" id="gw-tb-%u" checked/>' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync '<label for="gw-tb-%u">%s</label></li>\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync % ( WuiMain.ksParamGraphWizTestBoxIds, oTestBox.idTestBox, oTestBox.idTestBox,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ' </div>\n';
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # Build category selection.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync aidBuildCategories = list(self._dParams[WuiMain.ksParamGraphWizBuildCatIds]);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sEnd += ' <div id="graphwiz-buildcategories" class="graphwiz-end-selection-group">\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ' <h3>Build Category Selection:</h3>\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ' <ol class="tmgraph-buildcategories">\n';
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync for oBuildCat in self._oModel.getEligibleBuildCategories():
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync try: aidBuildCategories.remove(oBuildCat.idBuildCategory);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sEnd += ' <li><input type="checkbox" name="%s" value="%s" id="gw-bc-%u" %s/>' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync '<label for="gw-bc-%u">%s / %s / %s / %s</label></li>\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync % ( WuiMain.ksParamGraphWizBuildCatIds, oBuildCat.idBuildCategory, oBuildCat.idBuildCategory, sChecked,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync oBuildCat.sProduct, oBuildCat.sBranch, oBuildCat.sType, ' & '.join(oBuildCat.asOsArches) );
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync assert len(aidBuildCategories) == 0; # SQL should return all currently selected.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ' </div>\n';
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # Testcase variations.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sEnd += ' <div id="graphwiz-testcase-variations" class="graphwiz-end-selection-group">\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ' <h3>Miscellaneous:</h3>\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ' <input type="checkbox" id="%s" name="%s" value="1"%s/>\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ' <label for="%s">Separate by testcase variation.</label>\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ' </li>\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync % ( WuiMain.ksParamGraphWizSepTestVars, WuiMain.ksParamGraphWizSepTestVars,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ' checked' if self._dParams[WuiMain.ksParamGraphWizSepTestVars] else '',
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ' <lable for="%s">Test case ID:</label>\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ' <input type="text" id="%s" name="%s" value="%s" readonly/>\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ' </li>\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync WuiMain.ksParamGraphWizTestCaseIds, WuiMain.ksParamGraphWizTestCaseIds,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ','.join([str(i) for i in self._dParams[WuiMain.ksParamGraphWizTestCaseIds]]), );
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ' </div>\n';
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync #sEnd += ' <h3> </h3>\n';
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # Finish up the form.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sEnd += ' <div id="graphwiz-end-submit"><p>' + sFormButton + '</p></div>\n';
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync '</form>\n';
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # Quick mockup.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sHtml += '<h2>Incomplete code - no complaints yet, thank you!!</h2>\n';
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # Create a form for altering the data we're working with.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync (sTopOfForm, sEndOfForm) = self._generateInteractiveForm();
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # Emit the graphs. At least one per sample source.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync for iCollection, oCollection in enumerate(aoCollections):
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # Name the graph and add a checkbox for removing it.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sHtml += ' <div class="graphwiz-collection" id="graphwiz-source-%u">\n' % (iCollection,);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ' <input type="checkbox" name="%s" id="%s" value="%s:%s%s" checked class="graphwiz-src-input">\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ' <label for="%s">%s</label>\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ' </div>\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync % ( WuiMain.ksParamReportSubjectIds, WuiMain.ksParamReportSubjectIds, oCollection.sType,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ':'.join([str(idStr) for idStr in oCollection.aidStrTests]),
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ':%u' % oCollection.idStrValue if oCollection.idStrValue else '',
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # Split the series into sub-graphs as needed and produce SVGs.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync aaoSeries = self._splitSeries(oCollection.aoSeries);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # Gather the data for this graph. (Most big stuff is passed by
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # reference, so there shouldn't be any large memory penalty for
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # repacking the data here.)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if aoSeries[0].iUnit < len(constants.valueunit.g_asNames) and aoSeries[0].iUnit > 0:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sYUnit = constants.valueunit.g_asNames[aoSeries[0].iUnit];
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync oData = WuiHlpGraphDataTableEx(sXUnit = 'Build revision', sYUnit = sYUnit);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync fSeriesName = self._figureSeriesNameBits(aoSeries);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sSeriesName = self._getSeriesNameFromBits(oSeries, fSeriesName);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if len(oSeries.aoRevInfo) == len(oSeries.aiRevisions):
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync % ( utils.formatNumber(oSeries.aiErrorBarAbove[i]),
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sTooltip = '<table class=\'graphwiz-tt\'><tr><td>%s:</td><td>%s %s %s</td></tr>'\
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync '<tr><td>Rev:</td><td>r%s</td></tr>' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync #if sMsg.find('\n') >= 0:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # sMsg = sMsg[:sMsg.find('\n')].strip();
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sTooltip += '<tr><td>Author:</td><td>%s</td></tr>' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync '<tr><td>Date:</td><td>%s</td><tr>' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync '<tr><td>Message:</td><td>%s%s</td></tr>' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sMsg, '...' if len(oRevInfo.sMessage) > len(sMsg) else '');
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync oData.addDataSeries(sSeriesName, oSeries.aiRevisions, oSeries.aiValues, asHtmlTooltips,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # Render the data into a graph.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync oGraph = self.oGraphClass('tmgraph-%u' % (iGraph,), oData, self._oDisp);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync oGraph.setTitle(self._calcGraphName(aoSeries[0], fSeriesName, sSampleName));
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sHtml += ' <div class="graphwiz-graph" id="graphwiz-graph-%u">\n' % (iGraph,);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # Emit raw tabular data if requested.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sHtml += ' <div class="graphwiz-tab-div" id="graphwiz-tab-%u">\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ' <table class="tmtable graphwiz-tab">\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if aoSeries[0].iUnit < len(constants.valueunit.g_asNames) and aoSeries[0].iUnit > 0:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sUnit = constants.valueunit.g_asNames[aoSeries[0].iUnit];
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sColor = self.oGraphClass.calcSeriesColor(iSeries);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ' <tr class="graphwiz-tab graphwiz-tab-new-series-row">\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ' <th colspan="5"><span style="background-color:%s;"> </span> %s</th>\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ' </tr>\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ' <tr class="graphwiz-tab graphwiz-tab-col-hdr-row">\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ' <th>Revision</th><th>Value (%s)</th><th>Δmax</th><th>Δmin</th>' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync '<th>Samples</th>\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ' </tr>\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync '</thead>\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync self._getSeriesNameFromBits(oSeries, self.kfSeriesName_All & ~self.kfSeriesName_OsArchs),
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sHtml += ' <tr class="%s"><td>r%s</td><td>%s</td><td>+%s</td><td>-%s</td><td>%s</td></tr>\n' \
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync oSeries.aiErrorBarAbove[i], oSeries.aiErrorBarBelow[i],
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ' </div>\n';
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync # Finish the form.