7 Point.pointOnCircle = function(angle, radius)
9 return new Point(radius * Math.cos(angle), radius * Math.sin(angle));
12 Point.pointOnEllipse = function(angle, radiuses)
14 return new Point(radiuses.x * Math.cos(angle), radiuses.y * Math.sin(angle));
19 // Used when the point object is used as a size object.
25 // Used when the point object is used as a size object.
31 // Used when the point object is used as a size object.
34 return new Point(this.x / 2, this.y / 2);
39 return new Point(this.x + other.x, this.y + other.y);
42 subtract: function(other)
44 return new Point(this.x - other.x, this.y - other.y);
47 multiply: function(other)
49 return new Point(this.x * other.x, this.y * other.y);
52 move: function(angle, velocity, timeDelta)
54 return this.add(Point.pointOnCircle(angle, velocity * (timeDelta / 1000)));
58 function Insets(top, right, bottom, left)
69 return this.left + this.right;
73 return this.top + this.bottom;
77 function SimplePromise()
79 this._chainedPromise = null;
80 this._callback = null;
83 SimplePromise.prototype.then = function (callback)
86 throw "SimplePromise doesn't support multiple calls to then";
88 this._callback = callback;
89 this._chainedPromise = new SimplePromise;
92 this.resolve(this._resolvedValue);
94 return this._chainedPromise;
97 SimplePromise.prototype.resolve = function (value)
99 if (!this._callback) {
100 this._resolved = true;
101 this._resolvedValue = value;
105 var result = this._callback(value);
106 if (result instanceof SimplePromise) {
107 var chainedPromise = this._chainedPromise;
108 result.then(function (result) { chainedPromise.resolve(result); });
110 this._chainedPromise.resolve(result);
113 function Options(testInterval, frameRate)
115 this.testInterval = testInterval;
116 this.frameRate = frameRate;
119 function ProgressBar(element, ranges)
121 this.element = element;
122 this.ranges = ranges;
123 this.currentRange = 0;
126 ProgressBar.prototype =
128 _progressToPercent: function(progress)
130 return progress * (100 / this.ranges);
138 setPos: function(progress)
140 this.element.style.width = this._progressToPercent(this.currentRange + progress) + "%";
144 function RecordTable(element)
146 this.element = element;
150 RecordTable.prototype =
154 this.element.innerHTML = "";
157 _showTitles: function(row, queue, titles, message)
159 titles.forEach(function (title) {
160 var th = document.createElement("th");
161 th.textContent = title.text;
162 if (typeof message != "undefined" && message.length) {
163 th.appendChild(document.createElement('br'));
164 th.appendChild(document.createTextNode('[' + message +']'));
167 if ("width" in title)
168 th.width = title.width + "%";
170 queue.push({element: th, titles: title.children });
174 _showHeader: function(suiteName, titles, message)
176 var row = document.createElement("tr");
179 this._showTitles(row, queue, titles, message);
180 this.element.appendChild(row);
182 while (queue.length) {
186 for (var i = 0, len = queue.length; i < len; ++i) {
187 var entry = queue.shift();
189 if (!entry.titles.length) {
190 entries.push(entry.element);
195 var row = document.createElement("tr");
197 this._showTitles(row, queue, entry.titles, "");
198 entry.element.colSpan = entry.titles.length;
202 this.element.appendChild(row);
203 entries.forEach(function(entry) {
210 _showEmpty: function(row, testName)
212 var td = document.createElement("td");
216 _showValue: function(row, testName, value)
218 var td = document.createElement("td");
219 td.textContent = value.toFixed(2);
223 _showSamples: function(row, testName, axes, samples, samplingTimeOffset)
225 var td = document.createElement("td");
226 var button = document.createElement("div");
227 button.className = "small-button";
229 button.addEventListener("click", function() {
230 window.showGraph(testName, axes, samples, samplingTimeOffset);
233 button.textContent = "Graph...";
234 td.appendChild(button);
238 _showTest: function(testName, titles, sampler, finalResults)
240 var row = document.createElement("tr");
241 var td = document.createElement("td");
243 td.textContent = testName;
247 sampler.experiments.forEach(function(experiment, index) {
248 this._showValue(row, testName, experiment.mean());
249 this._showValue(row, testName, experiment.concern(Experiment.defaults.CONCERN));
250 this._showValue(row, testName, experiment.standardDeviation());
251 this._showValue(row, testName, experiment.percentage());
252 axes.push(titles[index + 1].text);
256 this._showValue(row, testName, sampler.experiments[0].score(Experiment.defaults.CONCERN));
259 this._showSamples(row, testName, axes, sampler.samples, sampler.samplingTimeOffset);
261 this._showEmpty(row, testName);
263 this.element.appendChild(row);
266 _showSuite: function(suite, suiteSamplers)
269 for (var testName in suiteSamplers) {
270 var test = testFromName(suite, testName);
271 var sampler = suiteSamplers[testName];
272 this._showTest(testName, suite.titles, sampler, true);
273 scores.push(sampler.experiments[0].score(Experiment.defaults.CONCERN));
278 showRecord: function(suite, test, sampler, message)
281 this._showHeader("", suite.titles, message);
282 this._showTest(test.name, suite.titles, sampler, false);
285 showIterations: function(iterationsSamplers)
291 iterationsSamplers.forEach(function(suitesSamplers) {
292 for (var suiteName in suitesSamplers) {
293 var suite = suiteFromName(suiteName);
294 if (titles != suite.titles) {
295 titles = suite.titles;
296 this._showHeader(suiteName, titles, "");
299 var suiteScores = this._showSuite(suite, suitesSamplers[suiteName]);
300 scores.push.apply(scores, suiteScores);
304 return Statistics.geometricMean(scores);