function()

in MotionMark/resources/runner/motionmark.js [26:287]


    function(version, options, testData)
    {
        this._iterationsSamplers = [];
        this._options = options;
        this._results = null;
        this._version = version;
        this._targetFrameRate = options["frame-rate"] || 60;
        this._systemFrameRate = options["system-frame-rate"] || 60;
        if (testData) {
            this._iterationsSamplers = testData;
            this._processData();
        }
    }, {

    push: function(suitesSamplers)
    {
        this._iterationsSamplers.push(suitesSamplers);
    },

    _processData: function()
    {
        this._results = {};
        this._results[Strings.json.results.iterations] = [];

        var iterationsScores = [];
        this._iterationsSamplers.forEach(function(iteration, index) {
            var testsScores = [];
            var testsLowerBoundScores = [];
            var testsUpperBoundScores = [];

            var result = {};
            this._results[Strings.json.results.iterations][index] = result;

            var suitesResult = {};
            result[Strings.json.results.tests] = suitesResult;

            for (var suiteName in iteration) {
                var suiteData = iteration[suiteName];

                var suiteResult = {};
                suitesResult[suiteName] = suiteResult;

                for (var testName in suiteData) {
                    if (!suiteData[testName][Strings.json.result])
                        this.calculateScore(suiteData[testName]);

                    suiteResult[testName] = suiteData[testName][Strings.json.result];
                    delete suiteData[testName][Strings.json.result];

                    testsScores.push(suiteResult[testName][Strings.json.score]);
                    testsLowerBoundScores.push(suiteResult[testName][Strings.json.scoreLowerBound]);
                    testsUpperBoundScores.push(suiteResult[testName][Strings.json.scoreUpperBound]);
                }
            }

            result[Strings.json.score] = Statistics.geometricMean(testsScores);
            result[Strings.json.scoreLowerBound] = Statistics.geometricMean(testsLowerBoundScores);
            result[Strings.json.scoreUpperBound] = Statistics.geometricMean(testsUpperBoundScores);
            iterationsScores.push(result[Strings.json.score]);
        }, this);

        this._results[Strings.json.version] = this._version;
        this._results[Strings.json.fps] = this._targetFrameRate;
        this._results[Strings.json.score] = Statistics.sampleMean(iterationsScores.length, iterationsScores.reduce(function(a, b) { return a + b; }));
        this._results[Strings.json.scoreLowerBound] = this._results[Strings.json.results.iterations][0][Strings.json.scoreLowerBound];
        this._results[Strings.json.scoreUpperBound] = this._results[Strings.json.results.iterations][0][Strings.json.scoreUpperBound];
    },

    calculateScore: function(data)
    {
        var result = {};
        data[Strings.json.result] = result;
        var samples = data[Strings.json.samples];

        function findRegression(series, profile) {
            var minIndex = Math.round(.025 * series.length);
            var maxIndex = Math.round(.975 * (series.length - 1));
            var minComplexity = series.getFieldInDatum(minIndex, Strings.json.complexity);
            var maxComplexity = series.getFieldInDatum(maxIndex, Strings.json.complexity);

            if (Math.abs(maxComplexity - minComplexity) < 20 && maxIndex - minIndex < 20) {
                minIndex = 0;
                maxIndex = series.length - 1;
                minComplexity = series.getFieldInDatum(minIndex, Strings.json.complexity);
                maxComplexity = series.getFieldInDatum(maxIndex, Strings.json.complexity);
            }

            var complexityIndex = series.fieldMap[Strings.json.complexity];
            var frameLengthIndex = series.fieldMap[Strings.json.frameLength];
            var regressionOptions = { desiredFrameLength: 1000/this._targetFrameRate };
            if (profile)
                regressionOptions.preferredProfile = profile;
            return {
                minComplexity: minComplexity,
                maxComplexity: maxComplexity,
                samples: series.slice(minIndex, maxIndex + 1),
                regression: new Regression(
                    series.data,
                    function (data, i) { return data[i][complexityIndex]; },
                    function (data, i) { return data[i][frameLengthIndex]; },
                    minIndex, maxIndex, regressionOptions)
            };
        }

        // Convert these samples into SampleData objects if needed
        [Strings.json.complexity, Strings.json.controller].forEach(function(seriesName) {
            var series = samples[seriesName];
            if (series && !(series instanceof SampleData))
                samples[seriesName] = new SampleData(series.fieldMap, series.data);
        });

        var isRampController = this._options["controller"] == "ramp";
        var predominantProfile = "";
        if (isRampController) {
            var profiles = {};
            data[Strings.json.controller].forEach(function(regression) {
                if (regression[Strings.json.regressions.profile]) {
                    var profile = regression[Strings.json.regressions.profile];
                    profiles[profile] = (profiles[profile] || 0) + 1;
                }
            });

            var maxProfileCount = 0;
            for (var profile in profiles) {
                if (profiles[profile] > maxProfileCount) {
                    predominantProfile = profile;
                    maxProfileCount = profiles[profile];
                }
            }
        }

        var regressionResult = findRegression(samples[Strings.json.complexity], predominantProfile);
        var calculation = regressionResult.regression;
        result[Strings.json.complexity] = {};
        result[Strings.json.complexity][Strings.json.regressions.segment1] = [
            [regressionResult.minComplexity, calculation.s1 + calculation.t1 * regressionResult.minComplexity],
            [calculation.complexity, calculation.s1 + calculation.t1 * calculation.complexity]
        ];
        result[Strings.json.complexity][Strings.json.regressions.segment2] = [
            [calculation.complexity, calculation.s2 + calculation.t2 * calculation.complexity],
            [regressionResult.maxComplexity, calculation.s2 + calculation.t2 * regressionResult.maxComplexity]
        ];
        result[Strings.json.complexity][Strings.json.complexity] = calculation.complexity;
        result[Strings.json.complexity][Strings.json.measurements.stdev] = Math.sqrt(calculation.error / samples[Strings.json.complexity].length);

        result[Strings.json.fps] = data.targetFPS || 60;

        if (isRampController) {
            var timeComplexity = new Experiment;
            data[Strings.json.controller].forEach(function(regression) {
                timeComplexity.sample(regression[Strings.json.complexity]);
            });

            var experimentResult = {};
            result[Strings.json.controller] = experimentResult;
            experimentResult[Strings.json.score] = timeComplexity.mean();
            experimentResult[Strings.json.measurements.average] = timeComplexity.mean();
            experimentResult[Strings.json.measurements.stdev] = timeComplexity.standardDeviation();
            experimentResult[Strings.json.measurements.percent] = timeComplexity.percentage();

            const bootstrapIterations = 2500;
            var bootstrapResult = Regression.bootstrap(regressionResult.samples.data, bootstrapIterations, function(resampleData) {
                var complexityIndex = regressionResult.samples.fieldMap[Strings.json.complexity];
                resampleData.sort(function(a, b) {
                    return a[complexityIndex] - b[complexityIndex];
                });

                var resample = new SampleData(regressionResult.samples.fieldMap, resampleData);
                var bootstrapRegressionResult = findRegression(resample, predominantProfile);
                return bootstrapRegressionResult.regression.complexity;
            }, .8);

            result[Strings.json.complexity][Strings.json.bootstrap] = bootstrapResult;
            result[Strings.json.score] = bootstrapResult.median;
            result[Strings.json.scoreLowerBound] = bootstrapResult.confidenceLow;
            result[Strings.json.scoreUpperBound] = bootstrapResult.confidenceHigh;
        } else {
            var marks = data[Strings.json.marks];
            var samplingStartIndex = 0, samplingEndIndex = -1;
            if (Strings.json.samplingStartTimeOffset in marks)
                samplingStartIndex = marks[Strings.json.samplingStartTimeOffset].index;
            if (Strings.json.samplingEndTimeOffset in marks)
                samplingEndIndex = marks[Strings.json.samplingEndTimeOffset].index;

            var averageComplexity = new Experiment;
            var averageFrameLength = new Experiment;
            var controllerSamples = samples[Strings.json.controller];
            controllerSamples.forEach(function (sample, i) {
                if (i >= samplingStartIndex && (samplingEndIndex == -1 || i < samplingEndIndex)) {
                    averageComplexity.sample(controllerSamples.getFieldInDatum(sample, Strings.json.complexity));
                    var smoothedFrameLength = controllerSamples.getFieldInDatum(sample, Strings.json.smoothedFrameLength);
                    if (smoothedFrameLength && smoothedFrameLength != -1)
                        averageFrameLength.sample(smoothedFrameLength);
                }
            });

            var experimentResult = {};
            result[Strings.json.controller] = experimentResult;
            experimentResult[Strings.json.measurements.average] = averageComplexity.mean();
            experimentResult[Strings.json.measurements.concern] = averageComplexity.concern(Experiment.defaults.CONCERN);
            experimentResult[Strings.json.measurements.stdev] = averageComplexity.standardDeviation();
            experimentResult[Strings.json.measurements.percent] = averageComplexity.percentage();

            experimentResult = {};
            result[Strings.json.frameLength] = experimentResult;
            experimentResult[Strings.json.measurements.average] = 1000 / averageFrameLength.mean();
            experimentResult[Strings.json.measurements.concern] = averageFrameLength.concern(Experiment.defaults.CONCERN);
            experimentResult[Strings.json.measurements.stdev] = averageFrameLength.standardDeviation();
            experimentResult[Strings.json.measurements.percent] = averageFrameLength.percentage();

            result[Strings.json.score] = averageComplexity.score(Experiment.defaults.CONCERN);
            result[Strings.json.scoreLowerBound] = result[Strings.json.score] - averageFrameLength.standardDeviation();
            result[Strings.json.scoreUpperBound] = result[Strings.json.score] + averageFrameLength.standardDeviation();
        }
    },

    get data()
    {
        return this._iterationsSamplers;
    },

    get results()
    {
        if (this._results)
            return this._results[Strings.json.results.iterations];
        this._processData();
        return this._results[Strings.json.results.iterations];
    },

    get options()
    {
        return this._options;
    },

    get version()
    {
        return this._version;
    },

    _getResultsProperty: function(property)
    {
        if (this._results)
            return this._results[property];
        this._processData();
        return this._results[property];
    },

    get score()
    {
        return this._getResultsProperty(Strings.json.score);
    },

    get scoreLowerBound()
    {
        return this._getResultsProperty(Strings.json.scoreLowerBound);
    },

    get scoreUpperBound()
    {
        return this._getResultsProperty(Strings.json.scoreUpperBound);
    }
});