12da489cd246702bee5938545b18a6f710ed214bcJamie Gennis// Copyright (c) 2012 The Chromium Authors. All rights reserved.
22da489cd246702bee5938545b18a6f710ed214bcJamie Gennis// Use of this source code is governed by a BSD-style license that can be
32da489cd246702bee5938545b18a6f710ed214bcJamie Gennis// found in the LICENSE file.
42da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
52da489cd246702bee5938545b18a6f710ed214bcJamie Gennis'use strict';
62da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
72da489cd246702bee5938545b18a6f710ed214bcJamie Gennis/**
82da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * @fileoverview TimelineAnalysis summarizes info about the selected slices
92da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * to the analysis panel.
102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis */
112da489cd246702bee5938545b18a6f710ed214bcJamie Gennisbase.require('ui');
122da489cd246702bee5938545b18a6f710ed214bcJamie Gennisbase.requireStylesheet('timeline_analysis');
132da489cd246702bee5938545b18a6f710ed214bcJamie Gennisbase.exportTo('tracing', function() {
142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  var AnalysisResults = base.ui.define('div');
162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  AnalysisResults.prototype = {
182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    __proto__: HTMLDivElement.prototype,
192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    decorate: function() {
212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    },
222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    tsRound_: function(ts) {
242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      return Math.round(ts * 1000.0) / 1000.0;
252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    },
262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    appendElement_: function(parent, tagName, opt_text) {
282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      var n = parent.ownerDocument.createElement(tagName);
292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      parent.appendChild(n);
302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      if (opt_text != undefined)
312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        n.textContent = opt_text;
322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      return n;
332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    },
342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    appendText_: function(parent, text) {
362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      var textElement = parent.ownerDocument.createTextNode(text);
372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      parent.appendChild(textNode);
382da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      return textNode;
392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    },
402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    appendTableCell_: function(table, row, cellnum, text) {
422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      var td = this.appendElement_(row, 'td', text);
432da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      td.className = table.className + '-col-' + cellnum;
442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      return td;
452da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    },
462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    appendTableCellWithTooltip_: function(table, row, cellnum, text, tooltip) {
482da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      if (tooltip) {
492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        var td = this.appendElement_(row, 'td');
502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        td.className = table.className + '-col-' + cellnum;
512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        var span = this.appendElement_(td, 'span', text);
522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        span.className = 'tooltip';
532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        span.title = tooltip;
542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        return td;
552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      } else {
562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        this.appendTableCell_(table, row, cellnum, text);
572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      }
582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    },
592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    /**
612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis     * Adds a table with the given className.
622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis     * @return {HTMLTableElement} The newly created table.
632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis     */
642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    appendTable: function(className, numColumns) {
652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      var table = this.appendElement_(this, 'table');
662da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      table.className = className + ' timeline-analysis-table';
672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      table.numColumns = numColumns;
682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      return table;
692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    },
702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    /**
722da489cd246702bee5938545b18a6f710ed214bcJamie Gennis     * Creates and appends a row to |table| with a left-aligned |label]
732da489cd246702bee5938545b18a6f710ed214bcJamie Gennis     * header that spans all columns.
742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis     */
752da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    appendTableHeader: function(table, label) {
762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      var row = this.appendElement_(table, 'tr');
772da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
782da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      var th = this.appendElement_(row, 'th', label);
792da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      th.className = 'timeline-analysis-table-header';
802da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    },
812da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
822da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    /**
832da489cd246702bee5938545b18a6f710ed214bcJamie Gennis     * Creates and appends a row to |table| with a left-aligned |label]
842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis     * in the first column and an optional |opt_text| value in the second
852da489cd246702bee5938545b18a6f710ed214bcJamie Gennis     * column.
862da489cd246702bee5938545b18a6f710ed214bcJamie Gennis     */
872da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    appendSummaryRow: function(table, label, opt_text) {
882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      var row = this.appendElement_(table, 'tr');
892da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      row.className = 'timeline-analysis-table-row';
902da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
912da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      this.appendTableCell_(table, row, 0, label);
922da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      if (opt_text !== undefined) {
932da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        this.appendTableCell_(table, row, 1, opt_text);
942da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        for (var i = 2; i < table.numColumns; i++)
952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          this.appendTableCell_(table, row, i, '');
962da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      } else {
972da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        for (var i = 1; i < table.numColumns; i++)
982da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          this.appendTableCell_(table, row, 1, '');
992da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      }
1002da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    },
1012da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1022da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    /**
1032da489cd246702bee5938545b18a6f710ed214bcJamie Gennis     * Adds a spacing row to spread out results.
1042da489cd246702bee5938545b18a6f710ed214bcJamie Gennis     */
1052da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    appendSpacingRow: function(table) {
1062da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      var row = this.appendElement_(table, 'tr');
1072da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      row.className = 'timeline-analysis-table-row';
1082da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      for (var i = 0; i < table.numColumns; i++)
1092da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        this.appendTableCell_(table, row, i, ' ');
1102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    },
1112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    /**
1132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis     * Creates and appends a row to |table| with a left-aligned |label]
1142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis     * in the first column and a millisecvond |time| value in the second
1152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis     * column.
1162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis     */
1172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    appendSummaryRowTime: function(table, label, time) {
1182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      this.appendSummaryRow(table, label, this.tsRound_(time) + ' ms');
1192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    },
1202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    /**
1222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis     * Creates and appends a row to |table| that summarizes one or more slices,
1232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis     * or one or more counters.
1242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis     * The row has a left-aligned |label| in the first column, the |duration|
1252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis     * of the data in the second, the number of |occurrences| in the third.
1262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis     * @param {object} opt_statistics May be undefined, or an object which
1272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis     * contains calculated staistics containing min/max/avg for slices, or
1282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis     * min/max/avg/start/end for counters.
1292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis     */
1302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    appendDataRow: function(
1312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        table, label, opt_duration, opt_occurences, opt_statistics) {
1322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      var tooltip = undefined;
1342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      if (opt_statistics) {
1352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        tooltip = 'Min Duration:\u0009' + this.tsRound_(opt_statistics.min) +
1362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                  ' ms \u000DMax Duration:\u0009' +
1372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                  this.tsRound_(opt_statistics.max) +
1382da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                  ' ms \u000DAvg Duration:\u0009' +
1392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                  this.tsRound_(opt_statistics.avg) + ' ms';
1402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        if (opt_statistics.start) {
1422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          tooltip += '\u000DStart Time:\u0009' +
1432da489cd246702bee5938545b18a6f710ed214bcJamie Gennis              this.tsRound_(opt_statistics.start) + ' ms';
1442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        }
1452da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        if (opt_statistics.end) {
1462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          tooltip += '\u000DEnd Time:\u0009' +
1472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis              this.tsRound_(opt_statistics.end) + ' ms';
1482da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        }
1492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        if (opt_statistics.frequency && opt_statistics.frequency_stddev) {
1502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          tooltip += '\u000DFrequency:\u0009' +
1512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis              this.tsRound_(opt_statistics.frequency) +
1522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis              ' occurrences/s (\u03C3 = ' +
1532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis              this.tsRound_(opt_statistics.frequency_stddev) + ')';
1542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        }
1552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      }
1562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      var row = this.appendElement_(table, 'tr');
1582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      row.className = 'timeline-analysis-table-row';
1592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      this.appendTableCellWithTooltip_(table, row, 0, label, tooltip);
1612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      if (opt_duration !== undefined) {
1632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        this.appendTableCellWithTooltip_(table, row, 1,
1642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            this.tsRound_(opt_duration) + ' ms', tooltip);
1652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      } else {
1662da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        this.appendTableCell_(table, row, 1, '');
1672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      }
1682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      if (opt_occurences !== undefined) {
1702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        this.appendTableCellWithTooltip_(table, row, 2,
1712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            String(opt_occurences) + ' occurrences', tooltip);
1722da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1732da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      } else {
1742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        this.appendTableCell_(table, row, 2, '');
1752da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      }
1762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    }
1772da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  };
1782da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1792da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  /**
1802da489cd246702bee5938545b18a6f710ed214bcJamie Gennis   * Analyzes the selection, outputting the analysis results into the provided
1812da489cd246702bee5938545b18a6f710ed214bcJamie Gennis   * results object.
1822da489cd246702bee5938545b18a6f710ed214bcJamie Gennis   *
1832da489cd246702bee5938545b18a6f710ed214bcJamie Gennis   * @param {AnalysisResults} results Where the analysis is placed.
1842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis   * @param {TimelineSelection} selection What to analyze.
1852da489cd246702bee5938545b18a6f710ed214bcJamie Gennis   */
1862da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  function analyzeSelection(results, selection) {
1872da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    var sliceHits = selection.getSliceHits();
1892da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    var counterSampleHits = selection.getCounterSampleHits();
1902da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1912da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    if (sliceHits.length == 1) {
1922da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      var slice = sliceHits[0].slice;
1932da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      var table = results.appendTable('timeline-analysis-slice-table', 2);
1942da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      results.appendTableHeader(table, 'Selected slice:');
1962da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      results.appendSummaryRow(table, 'Title', slice.title);
1972da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1982da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      if (slice.category)
1992da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        results.appendSummaryRow(table, 'Category', slice.category);
2002da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2012da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      results.appendSummaryRowTime(table, 'Start', slice.start);
2022da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      results.appendSummaryRowTime(table, 'Duration', slice.duration);
2032da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2042da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      if (slice.durationInUserTime) {
2052da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        results.appendSummaryRowTime(
2062da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            table, 'Duration (U)', slice.durationInUserTime);
2072da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      }
2082da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2092da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      var n = 0;
2102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      for (var argName in slice.args) {
2112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        n += 1;
2122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      }
2132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      if (n > 0) {
2142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        results.appendSummaryRow(table, 'Args');
2152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        for (var argName in slice.args) {
2162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          var argVal = slice.args[argName];
2172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          // TODO(sleffler) use span instead?
2182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          results.appendSummaryRow(table, ' ' + argName, argVal);
2192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        }
2202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      }
2212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    } else if (sliceHits.length > 1) {
2222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      var tsLo = sliceHits.range.min;
2232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      var tsHi = sliceHits.range.max;
2242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      // compute total sliceHits duration
2262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      var titles = sliceHits.map(function(i) { return i.slice.title; });
2272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      var numTitles = 0;
2292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      var slicesByTitle = {};
2302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      for (var i = 0; i < sliceHits.length; i++) {
2312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        var slice = sliceHits[i].slice;
2322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        if (!slicesByTitle[slice.title]) {
2332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          slicesByTitle[slice.title] = {
2342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            slices: []
2352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          };
2362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          numTitles++;
2372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        }
2382da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        slicesByTitle[slice.title].slices.push(slice);
2392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      }
2402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      var table;
2422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      table = results.appendTable('timeline-analysis-slices-table', 3);
2432da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      results.appendTableHeader(table, 'Slices:');
2442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2452da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      var totalDuration = 0;
2462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      for (var sliceGroupTitle in slicesByTitle) {
2472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        var sliceGroup = slicesByTitle[sliceGroupTitle];
2482da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        var duration = 0;
2492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        var avg = 0;
2502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        var startOfFirstOccurrence = Number.MAX_VALUE;
2512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        var startOfLastOccurrence = -Number.MAX_VALUE;
2522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        var frequencyDetails = undefined;
2532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        var min = Number.MAX_VALUE;
2542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        var max = -Number.MAX_VALUE;
2552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        for (var i = 0; i < sliceGroup.slices.length; i++) {
2562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          duration += sliceGroup.slices[i].duration;
2572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          startOfFirstOccurrence = Math.min(sliceGroup.slices[i].start,
2582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                                            startOfFirstOccurrence);
2592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          startOfLastOccurrence = Math.max(sliceGroup.slices[i].start,
2602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis              startOfLastOccurrence);
2612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          min = Math.min(sliceGroup.slices[i].duration, min);
2622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          max = Math.max(sliceGroup.slices[i].duration, max);
2632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        }
2642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        totalDuration += duration;
2662da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        if (sliceGroup.slices.length == 0)
2682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          avg = 0;
2692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        avg = duration / sliceGroup.slices.length;
2702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        var details = {min: min,
2722da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          max: max,
2732da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          avg: avg,
2742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          frequency: undefined,
2752da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          frequency_stddev: undefined};
2762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2772da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        // We require at least 3 samples to compute the stddev.
2782da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        var elapsed = startOfLastOccurrence - startOfFirstOccurrence;
2792da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        if (sliceGroup.slices.length > 2 && elapsed > 0) {
2802da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          var numDistances = sliceGroup.slices.length - 1;
2812da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          details.frequency = (1000 * numDistances) / elapsed;
2822da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2832da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          // Compute the stddev.
2842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          var sumOfSquaredDistancesToMean = 0;
2852da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          for (var i = 1; i < sliceGroup.slices.length; i++) {
2862da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            var currentFrequency = 1000 /
2872da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                (sliceGroup.slices[i].start - sliceGroup.slices[i - 1].start);
2882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            var signedDistance = details.frequency - currentFrequency;
2892da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            sumOfSquaredDistancesToMean += signedDistance * signedDistance;
2902da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          }
2912da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2922da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          details.frequency_stddev = Math.sqrt(
2932da489cd246702bee5938545b18a6f710ed214bcJamie Gennis              sumOfSquaredDistancesToMean / (numDistances - 1));
2942da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        }
2952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        results.appendDataRow(
2962da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            table, sliceGroupTitle, duration, sliceGroup.slices.length,
2972da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            details);
2982da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      }
2992da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      results.appendDataRow(table, '*Totals', totalDuration, sliceHits.length);
3002da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      results.appendSpacingRow(table);
3012da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      results.appendSummaryRowTime(table, 'Selection start', tsLo);
3022da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      results.appendSummaryRowTime(table, 'Selection extent', tsHi - tsLo);
3032da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    }
3042da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
3052da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    if (counterSampleHits.length == 1) {
3062da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      var hit = counterSampleHits[0];
3072da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      var ctr = hit.counter;
3082da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      var sampleIndex = hit.sampleIndex;
3092da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      var values = [];
3102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      for (var i = 0; i < ctr.numSeries; ++i)
3112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        values.push(ctr.samples[ctr.numSeries * sampleIndex + i]);
3122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
3132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      var table = results.appendTable('timeline-analysis-counter-table', 2);
3142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      results.appendTableHeader(table, 'Selected counter:');
3152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      results.appendSummaryRow(table, 'Title', ctr.name);
3162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      results.appendSummaryRowTime(
3172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          table, 'Timestamp', ctr.timestamps[sampleIndex]);
3182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
3192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      for (var i = 0; i < ctr.numSeries; i++)
3202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        results.appendSummaryRow(table, ctr.seriesNames[i], values[i]);
3212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    } else if (counterSampleHits.length > 1) {
3222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      var hitsByCounter = {};
3232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      for (var i = 0; i < counterSampleHits.length; i++) {
3242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        var ctr = counterSampleHits[i].counter;
3252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        if (!hitsByCounter[ctr.guid])
3262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          hitsByCounter[ctr.guid] = [];
3272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        hitsByCounter[ctr.guid].push(counterSampleHits[i]);
3282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      }
3292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
3302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      var table = results.appendTable('timeline-analysis-counter-table', 7);
3312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      results.appendTableHeader(table, 'Counters:');
3322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      for (var id in hitsByCounter) {
3332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        var hits = hitsByCounter[id];
3342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        var ctr = hits[0].counter;
3352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        var sampleIndices = [];
3362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        for (var i = 0; i < hits.length; i++)
3372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          sampleIndices.push(hits[i].sampleIndex);
3382da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
3392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        var stats = ctr.getSampleStatistics(sampleIndices);
3402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        for (var i = 0; i < stats.length; i++) {
3412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          results.appendDataRow(
3422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis              table, ctr.name + ': ' + ctr.seriesNames[i], undefined,
3432da489cd246702bee5938545b18a6f710ed214bcJamie Gennis              undefined, stats[i]);
3442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        }
3452da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      }
3462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    }
3472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  }
3482da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
3492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  var TimelineAnalysisView = base.ui.define('div');
3502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
3512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  TimelineAnalysisView.prototype = {
3522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    __proto__: HTMLDivElement.prototype,
3532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
3542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    decorate: function() {
3552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      this.className = 'timeline-analysis';
3562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    },
3572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
3582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    set selection(selection) {
3592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      this.textContent = '';
3602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      var results = new AnalysisResults();
3612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      analyzeSelection(results, selection);
3622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      this.appendChild(results);
3632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    }
3642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  };
3652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
3662da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  return {
3672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    TimelineAnalysisView: TimelineAnalysisView,
3682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    analyzeSelection_: analyzeSelection
3692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  };
3702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis});
371