66b13b7978a15215e13361ec8df348e044249190
[WebKit-https.git] / PerformanceTests / Animometer / resources / extensions.js
1 function Point(x, y)
2 {
3     this.x = x;
4     this.y = y;
5 }
6
7 Point.pointOnCircle = function(angle, radius)
8 {
9     return new Point(radius * Math.cos(angle), radius * Math.sin(angle));
10 }
11
12 Point.pointOnEllipse = function(angle, radiuses)
13 {
14     return new Point(radiuses.x * Math.cos(angle), radiuses.y * Math.sin(angle));
15 }
16
17 Point.prototype =
18 {
19     // Used when the point object is used as a size object.
20     get width()
21     {
22         return this.x;
23     },
24     
25     // Used when the point object is used as a size object.
26     get height()
27     {
28         return this.y;
29     },
30     
31     // Used when the point object is used as a size object.
32     get center()
33     {
34         return new Point(this.x / 2, this.y / 2);
35     },
36     
37     add: function(other)
38     {
39         return new Point(this.x + other.x, this.y + other.y);
40     },
41     
42     subtract: function(other)
43     {
44         return new Point(this.x - other.x, this.y - other.y);
45     },
46     
47     multiply: function(other)
48     {
49         return new Point(this.x * other.x, this.y * other.y);
50     },
51     
52     move: function(angle, velocity, timeDelta)
53     {
54         return this.add(Point.pointOnCircle(angle, velocity * (timeDelta / 1000)));
55     }
56 }
57
58 function Insets(top, right, bottom, left)
59 {
60     this.top = top;
61     this.right = right;
62     this.bottom = bottom;
63     this.left = left;
64 }
65
66 Insets.prototype =
67 {
68     get width() {
69         return this.left + this.right;
70     },
71
72     get height() {
73         return this.top + this.bottom;
74     }
75 }
76
77 function SimplePromise()
78 {
79     this._chainedPromise = null;
80     this._callback = null;
81 }
82
83 SimplePromise.prototype.then = function (callback)
84 {
85     if (this._callback)
86         throw "SimplePromise doesn't support multiple calls to then";
87         
88     this._callback = callback;
89     this._chainedPromise = new SimplePromise;
90     
91     if (this._resolved)
92         this.resolve(this._resolvedValue);
93
94     return this._chainedPromise;
95 }
96
97 SimplePromise.prototype.resolve = function (value)
98 {
99     if (!this._callback) {
100         this._resolved = true;
101         this._resolvedValue = value;
102         return;
103     }
104
105     var result = this._callback(value);
106     if (result instanceof SimplePromise) {
107         var chainedPromise = this._chainedPromise;
108         result.then(function (result) { chainedPromise.resolve(result); });
109     } else
110         this._chainedPromise.resolve(result);
111 }
112
113 function Options(testInterval, frameRate)
114 {
115     this.testInterval = testInterval;
116     this.frameRate = frameRate;
117 }
118
119 function ProgressBar(element, ranges)
120 {
121     this.element = element;
122     this.ranges = ranges;
123     this.currentRange = 0;
124 }
125
126 ProgressBar.prototype =
127 {
128     _progressToPercent: function(progress)
129     {
130         return progress * (100 / this.ranges);
131     },
132     
133     incRange: function()
134     {
135         ++this.currentRange;
136     },
137     
138     setPos: function(progress)
139     {
140         this.element.style.width = this._progressToPercent(this.currentRange + progress) + "%";
141     }
142 }
143
144 function RecordTable(element)
145 {
146     this.element = element;
147     this.clear();
148 }
149
150 RecordTable.prototype =
151 {
152     clear: function()
153     {
154         this.element.innerHTML = "";
155     },
156     
157     _showTitles: function(row, queue, titles, message)
158     {
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 +']'));
165                 message = "";
166             }
167             if ("width" in title)
168                 th.width = title.width + "%";
169             row.appendChild(th);
170             queue.push({element: th, titles: title.children });
171         });
172     },
173     
174     _showHeader: function(suiteName, titles, message)
175     {
176         var row = document.createElement("tr");
177
178         var queue = [];
179         this._showTitles(row, queue, titles, message);
180         this.element.appendChild(row);
181
182         while (queue.length) {
183             var row = null;
184             var entries = [];
185
186             for (var i = 0, len = queue.length; i < len; ++i) {
187                 var entry = queue.shift();
188
189                 if (!entry.titles.length) {
190                     entries.push(entry.element);
191                     continue;
192                 }
193
194                 if (!row)
195                     var row = document.createElement("tr");
196
197                 this._showTitles(row, queue, entry.titles, "");
198                 entry.element.colSpan = entry.titles.length;
199             }
200
201             if (row) {
202                 this.element.appendChild(row);
203                 entries.forEach(function(entry) {
204                     ++entry.rowSpan;
205                 });
206             }
207         }
208     },
209     
210     _showEmpty: function(row, testName)
211     {
212         var td = document.createElement("td");
213         row.appendChild(td);
214     },
215     
216     _showValue: function(row, testName, value)
217     {
218         var td = document.createElement("td");
219         td.textContent = value.toFixed(2);
220         row.appendChild(td);
221     },
222     
223     _showSamples: function(row, testName, axes, samples, samplingTimeOffset)
224     {
225         var td = document.createElement("td");
226         var button = document.createElement("div");
227         button.className = "small-button";
228             
229         button.addEventListener("click", function() {
230             window.showGraph(testName, axes, samples, samplingTimeOffset);
231         });
232             
233         button.textContent = "Graph...";
234         td.appendChild(button);
235         row.appendChild(td);
236     },
237     
238     _showTest: function(testName, titles, sampler, finalResults)
239     {
240         var row = document.createElement("tr");
241         var td = document.createElement("td");
242         
243         td.textContent = testName;
244         row.appendChild(td);
245         
246         var axes = [];
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);
253             
254         }, this);
255
256         this._showValue(row, testName, sampler.experiments[0].score(Experiment.defaults.CONCERN));
257
258         if (finalResults)
259             this._showSamples(row, testName, axes, sampler.samples, sampler.samplingTimeOffset);
260         else
261             this._showEmpty(row, testName);
262             
263         this.element.appendChild(row);
264     },
265     
266     _showSuite: function(suite, suiteSamplers)
267     {
268         var scores = [];        
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));
274         }
275         return scores;
276     },
277     
278     showRecord: function(suite, test, sampler, message)
279     {
280         this.clear();        
281         this._showHeader("", suite.titles, message);
282         this._showTest(test.name, suite.titles, sampler, false);        
283     },
284     
285     showIterations: function(iterationsSamplers)
286     {
287         this.clear();
288
289         var scores = [];
290         var titles = null;
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, "");
297                 }
298
299                 var suiteScores = this._showSuite(suite, suitesSamplers[suiteName]);
300                 scores.push.apply(scores, suiteScores);
301             }
302         }, this);
303
304         return Statistics.geometricMean(scores);
305     }
306 }