1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135

content / browser / webrtc / resources / data_series.js [blame]

// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// The maximum number of data points buffered for each stats. Old data points
// will be shifted out when the buffer is full.
export const MAX_STATS_DATA_POINT_BUFFER_SIZE = 1000;

/**
 * A TimelineDataSeries collects an ordered series of (time, value) pairs,
 * and converts them to graph points.  It also keeps track of its color and
 * current visibility state.
 * It keeps MAX_STATS_DATA_POINT_BUFFER_SIZE data points at most. Old data
 * points will be dropped when it reaches this size.
 */
export class TimelineDataSeries {
  constructor(statsType) {
    // List of DataPoints in chronological order.
    this.dataPoints_ = [];

    // Default color.  Should always be overridden prior to display.
    this.color_ = 'red';
    // Whether or not the data series should be drawn.
    this.isVisible_ = true;

    this.cacheStartTime_ = null;
    this.cacheStepSize_ = 0;
    this.cacheValues_ = [];
    this.statsType_ = statsType;
  }

  /**
   * @override
   */
  toJSON() {
    if (this.dataPoints_.length < 1) {
      return {};
    }

    const values = [];
    for (let i = 0; i < this.dataPoints_.length; ++i) {
      values.push(this.dataPoints_[i].value);
    }
    return {
      startTime: this.dataPoints_[0].time,
      endTime: this.dataPoints_[this.dataPoints_.length - 1].time,
      statsType: this.statsType_,
      values: JSON.stringify(values),
    };
  }

  /**
   * Adds a DataPoint to |this| with the specified time and value.
   * DataPoints are assumed to be received in chronological order.
   */
  addPoint(timeTicks, value) {
    const time = new Date(timeTicks);
    this.dataPoints_.push(new DataPoint(time, value));

    if (this.dataPoints_.length > MAX_STATS_DATA_POINT_BUFFER_SIZE) {
      this.dataPoints_.shift();
    }
  }

  isVisible() {
    return this.isVisible_;
  }

  show(isVisible) {
    this.isVisible_ = isVisible;
  }

  getColor() {
    return this.color_;
  }

  setColor(color) {
    this.color_ = color;
  }

  getCount() {
    return this.dataPoints_.length;
  }
  /**
   * Returns a list containing the values of the data series at |count|
   * points, starting at |startTime|, and |stepSize| milliseconds apart.
   * Caches values, so showing/hiding individual data series is fast.
   */
  getValues(startTime, stepSize, count) {
    // Use cached values, if we can.
    if (this.cacheStartTime_ === startTime &&
        this.cacheStepSize_ === stepSize &&
        this.cacheValues_.length === count) {
      return this.cacheValues_;
    }

    // Do all the work.
    this.cacheValues_ = this.getValuesInternal_(startTime, stepSize, count);
    this.cacheStartTime_ = startTime;
    this.cacheStepSize_ = stepSize;

    return this.cacheValues_;
  }

  /**
   * Returns the cached |values| in the specified time period.
   */
  getValuesInternal_(startTime, stepSize, count) {
    const values = [];
    let nextPoint = 0;
    let currentValue = 0;
    let time = startTime;
    for (let i = 0; i < count; ++i) {
      while (nextPoint < this.dataPoints_.length &&
             this.dataPoints_[nextPoint].time < time) {
        currentValue = this.dataPoints_[nextPoint].value;
        ++nextPoint;
      }
      values[i] = currentValue;
      time += stepSize;
    }
    return values;
  }
}

/**
 * A single point in a data series.  Each point has a time, in the form of
 * milliseconds since the Unix epoch, and a numeric value.
 */
class DataPoint {
  constructor(time, value) {
    this.time = time;
    this.value = value;
  }
}