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 /** 80 * Returns a list containing the values of the data series at |count| 81 * points, starting at |startTime|, and |stepSize| milliseconds apart. 82 * Caches values, so showing/hiding individual data series is fast. 83 */ 84 getValues: function(startTime, stepSize, count) { 85 // Use cached values, if we can. 86 if (this.cacheStartTime_ == startTime && 87 this.cacheStepSize_ == stepSize && 88 this.cacheValues_.length == count) { 89 return this.cacheValues_; 90 } 91 92 // Do all the work. 93 this.cacheValues_ = this.getValuesInternal_(startTime, stepSize, count); 94 this.cacheStartTime_ = startTime; 95 this.cacheStepSize_ = stepSize; 96 97 return this.cacheValues_; 98 }, 99 100 /** 101 * Returns the cached |values| in the specified time period. 102 */ 103 getValuesInternal_: function(startTime, stepSize, count) { 104 var values = []; 105 var nextPoint = 0; 106 var currentValue = 0; 107 var time = startTime; 108 for (var i = 0; i < count; ++i) { 109 while (nextPoint < this.dataPoints_.length && 110 this.dataPoints_[nextPoint].time < time) { 111 currentValue = this.dataPoints_[nextPoint].value; 112 ++nextPoint; 113 } 114 values[i] = currentValue; 115 time += stepSize; 116 } 117 return values; 118 } 119 }; 120 121 /** 122 * A single point in a data series. Each point has a time, in the form of 123 * milliseconds since the Unix epoch, and a numeric value. 124 * @constructor 125 */ 126 function DataPoint(time, value) { 127 this.time = time; 128 this.value = value; 129 } 130 131 return TimelineDataSeries; 132 })(); 133