1
2
3
4
5
6
7
8
9
10
11 package psiprobe.beans.stats.providers;
12
13 import jakarta.servlet.http.HttpServletRequest;
14
15 import java.util.ArrayList;
16 import java.util.Comparator;
17 import java.util.List;
18 import java.util.ListIterator;
19 import java.util.Map;
20
21 import org.jfree.data.xy.DefaultTableXYDataset;
22 import org.jfree.data.xy.XYDataItem;
23
24 import psiprobe.model.stats.StatsCollection;
25
26
27
28
29
30
31
32 public class MultipleSeriesProvider extends AbstractSeriesProvider {
33
34
35 private String statNamePrefix;
36
37
38 private int top;
39
40
41 private int movingAvgFrame;
42
43
44
45
46
47
48 public String getStatNamePrefix() {
49 return statNamePrefix;
50 }
51
52
53
54
55
56
57 public void setStatNamePrefix(String statNamePrefix) {
58 this.statNamePrefix = statNamePrefix;
59 }
60
61
62
63
64
65
66 public int getTop() {
67 return top;
68 }
69
70
71
72
73
74
75
76 public void setTop(int top) {
77 this.top = top;
78 }
79
80
81
82
83
84
85 public int getMovingAvgFrame() {
86 return movingAvgFrame;
87 }
88
89
90
91
92
93
94
95
96
97 public void setMovingAvgFrame(int movingAvgFrame) {
98 this.movingAvgFrame = movingAvgFrame;
99 }
100
101 @Override
102 public void populate(DefaultTableXYDataset dataset, StatsCollection statsCollection,
103 HttpServletRequest request) {
104
105 Map<String, List<XYDataItem>> statMap = statsCollection.getStatsByPrefix(statNamePrefix);
106 boolean useTop = getTop() > 0 && getTop() < statMap.size();
107 List<Series> seriesList = new ArrayList<>(statMap.size());
108
109 for (Map.Entry<String, List<XYDataItem>> entry : statMap.entrySet()) {
110 Series ser = new Series(entry);
111 if (useTop) {
112 ser.calculateAvg();
113 }
114 seriesList.add(ser);
115 }
116
117 if (useTop) {
118
119 seriesList.sort((s1, s2) -> Double.compare(s1.avg, s2.avg) == 0 ? s1.key.compareTo(s2.key)
120 : Double.compare(s1.avg, s2.avg) > 0 ? -1 : 1);
121
122
123 for (ListIterator<Series> i = seriesList.listIterator(getTop()); i.hasNext();) {
124 i.next();
125 i.remove();
126 }
127 }
128
129
130 seriesList.sort(Comparator.comparing(s1 -> s1.key));
131
132 for (Series ser : seriesList) {
133 synchronized (ser.stats) {
134 dataset.addSeries(toSeries(ser.key, ser.stats));
135 }
136 }
137 }
138
139
140
141
142
143 private class Series {
144
145
146 final String key;
147
148
149 final List<XYDataItem> stats;
150
151
152 double avg = 0;
153
154
155
156
157
158
159 Series(Map.Entry<String, List<XYDataItem>> en) {
160 key = en.getKey().substring(statNamePrefix.length());
161 stats = en.getValue();
162 }
163
164
165
166
167
168 void calculateAvg() {
169 long sum = 0;
170 int count = 1;
171
172 synchronized (stats) {
173 boolean useMovingAvg = getMovingAvgFrame() > 0 && getMovingAvgFrame() < stats.size();
174
175 for (ListIterator<XYDataItem> it = stats.listIterator(); it.hasNext();) {
176 XYDataItem xy = it.next();
177 sum += xy.getY().longValue();
178
179 if ((useMovingAvg && count % getMovingAvgFrame() == 0) || !it.hasNext()) {
180 double thisAvg = (double) sum / count;
181 if (thisAvg > avg) {
182 avg = thisAvg;
183 }
184 sum = 0;
185 count = 1;
186 } else {
187 count++;
188 }
189 }
190 }
191 }
192 }
193 }