forked from Pissandshittium/pissandshittium
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdata_series.js
133 lines (116 loc) · 3.51 KB
/
data_series.js
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
// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// 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() {
// 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_ = [];
}
/**
* @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,
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;
}
}