3 App.NameLabelModel = DS.Model.extend({
4 name: DS.attr('string'),
7 return this.get('name');
11 App.Test = App.NameLabelModel.extend({
12 url: DS.attr('string'),
13 parent: DS.belongsTo('test', {inverse: 'childTests'}),
14 childTests: DS.hasMany('test', {inverse: 'parent'}),
15 metrics: DS.hasMany('metrics'),
18 App.Metric = App.NameLabelModel.extend({
19 test: DS.belongsTo('test'),
20 aggregator: DS.attr('string'),
23 return this.get('name') + (this.get('aggregator') ? ' : ' + this.get('aggregator') : '');
24 }.property('name', 'aggregator'),
28 var parent = this.get('test');
30 path.push(parent.get('name'));
31 parent = parent.get('parent');
33 return path.reverse();
34 }.property('name', 'test'),
37 return this.get('path').join(' \u220b ') /* ∈ */
38 + ' : ' + this.get('label');
39 }.property('path', 'label'),
42 App.Builder = App.NameLabelModel.extend({
43 buildUrl: DS.attr('string'),
44 urlFromBuildNumber: function (buildNumber)
46 var template = this.get('buildUrl');
47 return template ? template.replace(/\$builderName/g, this.get('name')).replace(/\$buildNumber/g, buildNumber) : null;
51 App.BugTracker = App.NameLabelModel.extend({
52 bugUrl: DS.attr('string'),
53 newBugUrl: DS.attr('string'),
54 repositories: DS.hasMany('repository'),
57 App.DateArrayTransform = DS.Transform.extend({
58 deserialize: function (serialized)
60 return serialized.map(function (time) { return new Date(time); });
64 App.Platform = App.NameLabelModel.extend({
67 metrics: DS.hasMany('metric'),
68 lastModified: DS.attr('dateArray'),
69 containsMetric: function (metric)
72 this._metricSet = new Ember.Set(this.get('metrics'));
73 return this._metricSet.contains(metric);
75 lastModifiedTimeForMetric: function (metric)
77 var index = this.get('metrics').indexOf(metric);
80 return this.get('lastModified').objectAt(index);
82 containsTest: function (test)
85 var set = new Ember.Set();
86 this.get('metrics').forEach(function (metric) {
87 for (var test = metric.get('test'); test; test = test.get('parent'))
92 return this._testSet.contains(test);
96 App.Repository = App.NameLabelModel.extend({
97 url: DS.attr('string'),
98 blameUrl: DS.attr('string'),
99 hasReportedCommits: DS.attr('boolean'),
100 urlForRevision: function (currentRevision)
102 return (this.get('url') || '').replace(/\$1/g, currentRevision);
104 urlForRevisionRange: function (from, to)
106 return (this.get('blameUrl') || '').replace(/\$1/g, from).replace(/\$2/g, to);
110 App.Dashboard = App.NameLabelModel.extend({
111 serialized: DS.attr('string'),
114 var json = this.get('serialized');
116 var parsed = JSON.parse(json);
118 console.log("Failed to parse the grid:", error, json);
123 return this._normalizeTable(parsed);
124 }.property('serialized'),
128 return this.get('table').slice(1);
131 headerColumns: function ()
133 var table = this.get('table');
134 if (!table || !table.length)
136 return table[0].map(function (name, index) {
137 return {label:name, index: index};
141 _normalizeTable: function (table)
143 var maxColumnCount = Math.max(table.map(function (column) { return column.length; }));
144 for (var i = 1; i < table.length; i++) {
146 for (var j = 1; j < row.length; j++) {
147 if (row[j] && !(row[j] instanceof Array)) {
148 console.log('Unrecognized (platform, metric) pair at column ' + i + ' row ' + j + ':' + row[j]);
157 App.MetricSerializer = App.PlatformSerializer = DS.RESTSerializer.extend({
158 normalizePayload: function (payload)
161 platforms: this._normalizeIdMap(payload['all']),
162 builders: this._normalizeIdMap(payload['builders']),
163 tests: this._normalizeIdMap(payload['tests']).map(function (test) {
164 test['parent'] = test['parentId'];
167 metrics: this._normalizeIdMap(payload['metrics']),
168 repositories: this._normalizeIdMap(payload['repositories']),
169 bugTrackers: this._normalizeIdMap(payload['bugTrackers']),
173 for (var testId in payload['tests']) {
174 var test = payload['tests'][testId];
175 var parent = payload['tests'][test['parent']];
178 if (!parent['childTests'])
179 parent['childTests'] = [];
180 parent['childTests'].push(testId);
183 for (var metricId in payload['metrics']) {
184 var metric = payload['metrics'][metricId];
185 var test = payload['tests'][metric['test']];
186 if (!test['metrics'])
187 test['metrics'] = [];
188 test['metrics'].push(metricId);
192 var dashboardsInPayload = payload['dashboards'];
193 for (var dashboardName in dashboardsInPayload) {
194 results['dashboards'].push({
197 serialized: JSON.stringify(dashboardsInPayload[dashboardName])
204 _normalizeIdMap: function (idMap)
207 for (var id in idMap) {
208 var definition = idMap[id];
209 definition['id'] = id;
210 results.push(definition);
216 App.PlatformAdapter = DS.RESTAdapter.extend({
217 buildURL: function (type, id)
219 return '../data/manifest.json';
223 App.MetricAdapter = DS.RESTAdapter.extend({
224 buildURL: function (type, id)
226 return '../data/manifest.json';
230 App.Manifest = Ember.Controller.extend({
234 repositoriesWithReportedCommits: [],
240 _dashboardByName: {},
241 _defaultDashboardName: null,
243 fetch: function (store)
245 if (!this._fetchPromise)
246 this._fetchPromise = store.findAll('platform').then(this._fetchedManifest.bind(this, store));
247 return this._fetchPromise;
249 isFetched: function () { return !!this.get('platforms'); }.property('platforms'),
250 platform: function (id) { return this._platformById[id]; },
251 metric: function (id) { return this._metricById[id]; },
252 builder: function (id) { return this._builderById[id]; },
253 repository: function (id) { return this._repositoryById[id]; },
254 dashboardByName: function (name) { return this._dashboardByName[name]; },
255 defaultDashboardName: function () { return this._defaultDashboardName; },
256 _fetchedManifest: function (store)
258 var startTime = Date.now();
261 var topLevelTests = [];
262 store.all('test').forEach(function (test) {
263 var parent = test.get('parent');
265 topLevelTests.push(test);
267 this.set('topLevelTests', topLevelTests);
269 store.all('metric').forEach(function (metric) {
270 self._metricById[metric.get('id')] = metric;
272 var platforms = store.all('platform');
273 platforms.forEach(function (platform) {
274 self._platformById[platform.get('id')] = platform;
276 this.set('platforms', platforms);
278 store.all('builder').forEach(function (builder) {
279 self._builderById[builder.get('id')] = builder;
282 var repositories = store.all('repository');
283 repositories.forEach(function (repository) {
284 self._repositoryById[repository.get('id')] = repository;
286 this.set('repositories', repositories.sortBy('id'));
287 this.set('repositoriesWithReportedCommits',
288 repositories.filter(function (repository) { return repository.get('hasReportedCommits'); }));
290 this.set('bugTrackers', store.all('bugTracker').sortBy('name'));
292 var dashboards = store.all('dashboard').sortBy('name');
293 this.set('dashboards', dashboards);
294 dashboards.forEach(function (dashboard) { self._dashboardByName[dashboard.get('name')] = dashboard; });
295 this._defaultDashboardName = dashboards.length ? dashboards[0].get('name') : null;
297 fetchRunsWithPlatformAndMetric: function (store, platformId, metricId, testGroupId, useCache)
299 Ember.assert("Can't cache results for test groups", !(testGroupId && useCache));
301 return Ember.RSVP.all([
302 RunsData.fetchRuns(platformId, metricId, testGroupId, useCache),
304 ]).then(function (values) {
305 var response = values[0];
307 var platform = App.Manifest.platform(platformId);
308 var metric = App.Manifest.metric(metricId);
313 data: response ? self._formatFetchedData(metric.get('name'), response.configurations) : null,
314 shouldRefetch: !response || +response.lastModified < +platform.lastModifiedTimeForMetric(metric),
318 _formatFetchedData: function (metricName, configurations)
320 var suffix = metricName.match('([A-z][a-z]+|FrameRate)$')[0];
327 'Allocations': 'bytes'
330 var smallerIsBetter = unit != 'fps' && unit != '/s'; // Assume smaller is better for unit-less metrics.
332 var useSI = unit == 'bytes';
333 var unitSuffix = unit ? ' ' + unit : '';
334 var deltaFormatterWithoutSign = useSI ? d3.format('.2s') : d3.format('.2g');
337 current: configurations.current.timeSeriesByCommitTime(),
338 baseline: configurations.baseline ? configurations.baseline.timeSeriesByCommitTime() : null,
339 target: configurations.target ? configurations.target.timeSeriesByCommitTime() : null,
341 formatWithUnit: function (value) { return this.formatter(value) + unitSuffix; },
342 formatWithDeltaAndUnit: function (value, delta)
344 return this.formatter(value) + (delta && !isNaN(delta) ? ' \u00b1 ' + deltaFormatterWithoutSign(delta) : '') + unitSuffix;
346 formatter: useSI ? d3.format('.4s') : d3.format('.4g'),
347 deltaFormatter: useSI ? d3.format('+.2s') : d3.format('+.2g'),
348 smallerIsBetter: smallerIsBetter,