1
2
3
4
5
6
7
8
9
10
11 package psiprobe.jsp;
12
13 import jakarta.servlet.jsp.JspException;
14 import jakarta.servlet.jsp.tagext.BodyContent;
15 import jakarta.servlet.jsp.tagext.BodyTagSupport;
16
17 import java.io.IOException;
18 import java.text.MessageFormat;
19
20
21
22
23 public class VisualScoreTag extends BodyTagSupport {
24
25
26 private static final long serialVersionUID = -5653846466205838602L;
27
28
29
30 private static final String WHITE_LEFT_BORDER = "a0";
31
32
33 private static final String RED_LEFT_BORDER = "a1";
34
35
36 private static final String BLUE_LEFT_BORDER = "a2";
37
38
39 private static final String WHITE_RIGHT_BORDER = "b0";
40
41
42 private static final String RED_RIGHT_BORDER = "b1";
43
44
45 private static final String BLUE_RIGHT_BORDER = "b2";
46
47
48 private double value = 0;
49
50
51 private double value2 = 0;
52
53
54 private double minValue = 0;
55
56
57 private double maxValue = 100;
58
59
60
61
62
63
64 private int partialBlocks = 1;
65
66
67
68
69
70
71 private int fullBlocks = 5;
72
73
74 private boolean showEmptyBlocks;
75
76
77 private boolean showA;
78
79
80 private boolean showB;
81
82 @Override
83 public int doAfterBody() throws JspException {
84 try (BodyContent bc = getBodyContent()) {
85 String body = bc.getString().trim();
86
87 String buf = calculateSuffix(body);
88
89 bc.getEnclosingWriter().print(buf);
90 } catch (IOException e) {
91 throw new JspException("Exception while writing to client", e);
92 }
93
94 return SKIP_BODY;
95 }
96
97
98
99
100
101
102
103
104 String calculateSuffix(String body) {
105 if (value < minValue) {
106 value = minValue;
107 }
108 if (value > maxValue) {
109 value = maxValue;
110 }
111 if (value + value2 < minValue || value2 < 0) {
112 value2 = 0;
113 }
114 if (value + value2 > maxValue) {
115 value2 = maxValue - value;
116 }
117
118 double unitSize = (maxValue - minValue) / (fullBlocks * partialBlocks);
119 double blockWidth = unitSize * partialBlocks;
120
121 int redWhole = (int) Math.floor(value / blockWidth);
122 int redPart = (int) Math.floor((value - redWhole * blockWidth) / unitSize);
123 int bluePart1 =
124 redPart > 0 ? Math.min((int) Math.floor(value2 / unitSize), partialBlocks - redPart) : 0;
125 int blueWhole = (int) Math.max(0, Math.ceil(value2 / blockWidth) - (redPart > 0 ? 1 : 0));
126 int bluePart2 =
127 (int) Math.floor((value2 - blueWhole * blockWidth - bluePart1 * unitSize) / unitSize);
128
129 StringBuilder buf = new StringBuilder();
130
131
132 if (showA) {
133 String format = WHITE_LEFT_BORDER;
134 if (redWhole > 0 || redPart > 0) {
135 format = RED_LEFT_BORDER;
136 } else if (bluePart1 == 0 && (blueWhole > 0 || bluePart2 > 0)) {
137
138 format = BLUE_LEFT_BORDER;
139 }
140 buf.append(MessageFormat.format(body, format));
141 }
142
143
144 String fullRedBody = MessageFormat.format(body, partialBlocks + "+0");
145 for (int i = 0; i < redWhole; i++) {
146 buf.append(fullRedBody);
147 }
148
149
150 if (redPart > 0) {
151 String partialBody = MessageFormat.format(body, redPart + "+" + bluePart1);
152 buf.append(partialBody);
153 }
154
155
156 String fullBlueBody = MessageFormat.format(body, "0+" + partialBlocks);
157 for (int i = 0; i < blueWhole; i++) {
158 buf.append(fullBlueBody);
159 }
160
161
162 if (bluePart2 > 0) {
163 String partialBody = MessageFormat.format(body, "0+" + bluePart2);
164 buf.append(partialBody);
165 }
166
167
168 int emptyBlocks = showEmptyBlocks
169 ? fullBlocks - (redWhole + blueWhole + (redPart > 0 ? 1 : 0) + (bluePart2 > 0 ? 1 : 0))
170 : 0;
171 if (emptyBlocks > 0) {
172 String emptyBody = MessageFormat.format(body, "0+0");
173 for (int i = 0; i < emptyBlocks; i++) {
174 buf.append(emptyBody);
175 }
176 }
177
178
179 if (showB) {
180 String format = WHITE_RIGHT_BORDER;
181 if (redWhole == fullBlocks) {
182 format = RED_RIGHT_BORDER;
183 } else if (redWhole + (redPart + bluePart1 == partialBlocks ? 1 : 0)
184 + blueWhole == fullBlocks) {
185 format = BLUE_RIGHT_BORDER;
186 }
187 buf.append(MessageFormat.format(body, format));
188 }
189
190 return buf.toString();
191 }
192
193
194
195
196
197
198 public double getValue() {
199 return value;
200 }
201
202
203
204
205
206
207 public void setValue(double value) {
208 this.value = value;
209 }
210
211
212
213
214
215
216 public double getValue2() {
217 return value2;
218 }
219
220
221
222
223
224
225 public void setValue2(double value2) {
226 this.value2 = value2;
227 }
228
229
230
231
232
233
234 public double getMinValue() {
235 return minValue;
236 }
237
238
239
240
241
242
243 public void setMinValue(double minValue) {
244 this.minValue = minValue;
245 }
246
247
248
249
250
251
252 public double getMaxValue() {
253 return maxValue;
254 }
255
256
257
258
259
260
261 public void setMaxValue(double maxValue) {
262 this.maxValue = maxValue;
263 }
264
265
266
267
268
269
270 public int getPartialBlocks() {
271 return partialBlocks;
272 }
273
274
275
276
277
278
279 public void setPartialBlocks(int partialBlocks) {
280 this.partialBlocks = partialBlocks;
281 }
282
283
284
285
286
287
288 public int getFullBlocks() {
289 return fullBlocks;
290 }
291
292
293
294
295
296
297 public void setFullBlocks(int fullBlocks) {
298 this.fullBlocks = fullBlocks;
299 }
300
301
302
303
304
305
306 public boolean isShowEmptyBlocks() {
307 return showEmptyBlocks;
308 }
309
310
311
312
313
314
315 public void setShowEmptyBlocks(boolean showEmptyBlocks) {
316 this.showEmptyBlocks = showEmptyBlocks;
317 }
318
319
320
321
322
323
324 public boolean isShowA() {
325 return showA;
326 }
327
328
329
330
331
332
333 public void setShowA(boolean showA) {
334 this.showA = showA;
335 }
336
337
338
339
340
341
342 public boolean isShowB() {
343 return showB;
344 }
345
346
347
348
349
350
351 public void setShowB(boolean showB) {
352 this.showB = showB;
353 }
354
355 }