1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 /** 6 * A TimelineDataSeries collects an ordered series of (time, value) pairs, 7 * and converts them to graph points. It also keeps track of its color and 8 * current visibility state. 9 * It keeps MAX_STATS_DATA_POINT_BUFFER_SIZE data points at most. Old data 10 * points will be dropped when it reaches this size. 11 */ 12 var TimelineDataSeries = (function() { 13 'use strict'; 14 15 /** 16 * @constructor 17 */ 18 function TimelineDataSeries() { 19 // List of DataPoints in chronological order. 20 this.dataPoints_ = []; 21 22 // Default color. Should always be overridden prior to display. 23 this.color_ = 'red'; 24 // Whether or not the data series should be drawn. 25 this.isVisible_ = true; 26 27 this.cacheStartTime_ = null; 28 this.cacheStepSize_ = 0; 29 this.cacheValues_ = []; 30 } 31 32 TimelineDataSeries.prototype = { 33 /** 34 * @override 35 */ 36 toJSON: function() { 37 if (this.dataPoints_.length < 1) 38 return {}; 39 40 var values = []; 41 for (var i = 0; i < this.dataPoints_.length; ++i) { 42 values.push(this.dataPoints_[i].value); 43 } 44 return { 45 startTime: this.dataPoints_[0].time, 46 endTime: this.dataPoints_[this.dataPoints_.length - 1].time, 47 values: JSON.stringify(values), 48 }; 49 }, 50 51 /** 52 * Adds a DataPoint to |this| with the specified time and value. 53 * DataPoints are assumed to be received in chronological order. 54 */ 55 addPoint: function(timeTicks, value) { 56 var time = new Date(timeTicks); 57 this.dataPoints_.push(new DataPoint(time, value)); 58 59 if (this.dataPoints_.length > MAX_STATS_DATA_POINT_BUFFER_SIZE) 60 this.dataPoints_.shift(); 61 }, 62 63 isVisible: function() { 64 return this.isVisible_; 65 }, 66 67 show: function(isVisible) { 68 this.isVisible_ = isVisible; 69 }, 70 71 getColor: function() { 72 return this.color_; 73 }, 74 75 setColor: function(color) { 76 this.color_ = color; 77 }, 78 79 getCount: function() { 80 return this.dataPoints_.length; 81 }, 82 /** 83 * Returns a list containing the values of the data series at |count| 84 * points, starting at |startTime|, and |stepSize| milliseconds apart. 85 * Caches values, so showing/hiding individual data series is fast. 86 */ 87 getValues: function(startTime, stepSize, count) { 88 // Use cached values, if we can. 89 if (this.cacheStartTime_ == startTime && 90 this.cacheStepSize_ == stepSize && 91 this.cacheValues_.length == count) { 92 return this.cacheValues_; 93 } 94 95 // Do all the work. 96 this.cacheValues_ = this.getValuesInternal_(startTime, stepSize, count); 97 this.cacheStartTime_ = startTime; 98 this.cacheStepSize_ = stepSize; 99 100 return this.cacheValues_; 101 }, 102 103 /** 104 * Returns the cached |values| in the specified time period. 105 */ 106 getValuesInternal_: function(startTime, stepSize, count) { 107 var values = []; 108 var nextPoint = 0; 109 var currentValue = 0; 110 var time = startTime; 111 for (var i = 0; i < count; ++i) { 112 while (nextPoint < this.dataPoints_.length && 113 this.dataPoints_[nextPoint].time < time) { 114 currentValue = this.dataPoints_[nextPoint].value; 115 ++nextPoint; 116 } 117 values[i] = currentValue; 118 time += stepSize; 119 } 120 return values; 121 } 122 }; 123 124 /** 125 * A single point in a data series. Each point has a time, in the form of 126 * milliseconds since the Unix epoch, and a numeric value. 127 * @constructor 128 */ 129 function DataPoint(time, value) { 130 this.time = time; 131 this.value = value; 132 } 133 134 return TimelineDataSeries; 135 })(); 136