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