8 |
8 |
import java.util.ArrayList;
|
9 |
9 |
import java.util.List;
|
10 |
10 |
import java.util.Map;
|
|
11 |
import java.util.Stack;
|
11 |
12 |
import java.util.concurrent.TimeUnit;
|
12 |
13 |
|
13 |
14 |
/**
|
... | ... | |
15 |
16 |
*/
|
16 |
17 |
public class Converter {
|
17 |
18 |
|
|
19 |
/**
|
|
20 |
* Name of the table
|
|
21 |
*/
|
|
22 |
private final String tableName;
|
|
23 |
|
18 |
24 |
/**
|
19 |
25 |
* Stores information about whether user set switch to show empty rows and columns to ON.
|
20 |
26 |
*/
|
... | ... | |
57 |
63 |
* @param columnNames List of names and user names of selected columns.
|
58 |
64 |
* @param valueFunctions List of information about selected value and functions.
|
59 |
65 |
* @param isNotRemoveEmpty Stores information about whether user set switch to show empty rows and columns to ON.
|
|
66 |
* @param tableName Name of the table.
|
60 |
67 |
*/
|
61 |
68 |
public Converter(Map<String, TableColumn> tableColumns, List<NameUserName> rowNames, List<NameUserName> columnNames,
|
62 |
|
List<ValueFunction> valueFunctions, boolean isNotRemoveEmpty) {
|
|
69 |
List<ValueFunction> valueFunctions, boolean isNotRemoveEmpty, String tableName) {
|
63 |
70 |
this.tableColumns = tableColumns;
|
64 |
71 |
this.rowNames = rowNames;
|
65 |
72 |
this.columnNames = columnNames;
|
66 |
73 |
this.valueFunctions = valueFunctions;
|
67 |
74 |
this.isNotRemoveEmpty = isNotRemoveEmpty;
|
|
75 |
this.tableName = tableName;
|
68 |
76 |
}
|
69 |
77 |
|
70 |
78 |
/**
|
... | ... | |
148 |
156 |
ContingencyTableRow headerRow = headerRows.get(i);
|
149 |
157 |
|
150 |
158 |
if (i == 0) {
|
151 |
|
headerRow.addTableRowCell(new ContingencyTableRowCell("Tabulka", 1));
|
|
159 |
headerRow.addTableRowCell(new ContingencyTableRowCell(tableName, 1));
|
152 |
160 |
}
|
153 |
161 |
else {
|
154 |
162 |
headerRow.addTableRowCell(new ContingencyTableRowCell("", 1));
|
155 |
163 |
}
|
156 |
164 |
}
|
157 |
165 |
|
158 |
|
|
159 |
|
List<String> prevValues = new ArrayList<>();
|
160 |
|
int prevSize = 0;
|
161 |
|
for (ValueFunction valueFunction : valueFunctions) {
|
|
166 |
List<String> prevValues = new ArrayList<>(); // values that were visited
|
|
167 |
int prevSize = 0; // number of previous column node values
|
|
168 |
for (ValueFunction valueFunction : valueFunctions) { // for each function
|
|
169 |
// add cell with the function name and value name to the 0th row with span 0
|
162 |
170 |
headerRows.get(0).addTableRowCell(new ContingencyTableRowCell(valueFunction.getFunction() + " z " + valueFunction.getParameterName(), 0));
|
163 |
|
for (Node columnNode : columnNodes) {
|
164 |
|
for (int i = 0; i < columnNode.getValues().size(); i++) {
|
|
171 |
for (Node columnNode : columnNodes) { // for each column
|
|
172 |
for (int i = 0; i < columnNode.getValues().size(); i++) { // for each value in column
|
165 |
173 |
String value = columnNode.getValues().get(i);
|
166 |
|
if (!prevValues.contains(value)) {
|
|
174 |
// check if value is not in the visited list, if list size equals i, the value is not visited
|
|
175 |
// eg. i = 0 -> no values in the list, if list size is bigger than i, there are more values than i
|
|
176 |
// so then check if value at ith position is not equal to the current value (is not visited)
|
|
177 |
if (prevValues.size() == i || (prevValues.size() > i && !prevValues.get(i).equals(value))) {
|
167 |
178 |
prevValues.add(value);
|
|
179 |
// add cell with value with span 0 to the i + 1th row (0th is for function name and value name cells)
|
168 |
180 |
headerRows.get(i + 1).addTableRowCell(new ContingencyTableRowCell(columnNames.get(i).getUserName() + " - " + value, 1));
|
|
181 |
// add 1 to the span of the last added function and value name cell
|
169 |
182 |
headerRows.get(0).getCells().get(headerRows.get(0).getCells().size() - 1).setColSpan(headerRows.get(0).getCells().get(headerRows.get(0).getCells().size() - 1).getColSpan() + 1);
|
170 |
183 |
} else if (columnNode.getValues().size() >= prevSize) {
|
|
184 |
// add 1 to the span of the last added cell of the row of i + 1th value
|
171 |
185 |
headerRows.get(i + 1).getCells().get(headerRows.get(i + 1).getCells().size() - 1).setColSpan(headerRows.get(i + 1).getCells().get(headerRows.get(i + 1).getCells().size() - 1).getColSpan() + 1);
|
172 |
186 |
}
|
173 |
187 |
}
|
174 |
188 |
|
175 |
|
if (columnNode.getValues().size() < prevSize) {
|
|
189 |
if (columnNode.getValues().size() < prevSize) { // if there are less values than in previous column node
|
176 |
190 |
for (int s = prevSize; s < headerRows.size(); s++) {
|
|
191 |
// add blank cell to the rows bellow
|
177 |
192 |
headerRows.get(s).addTableRowCell(new ContingencyTableRowCell("", 1));
|
178 |
193 |
}
|
179 |
194 |
for (int s = 1; s < columnNode.getValues().size(); s++) {
|
|
195 |
// add 1 to colspan to the cells above
|
180 |
196 |
headerRows.get(s).getCells().get(headerRows.get(s).getCells().size() - 1).setColSpan(headerRows.get(s).getCells().get(headerRows.get(s).getCells().size() - 1).getColSpan() + 1);
|
181 |
197 |
}
|
|
198 |
// create cell for total values (not for lists of the tree)
|
182 |
199 |
headerRows.get(columnNode.getValues().size()).addTableRowCell(new ContingencyTableRowCell(columnNode.getValues().get(columnNode.getValues().size() - 1) + " Celkem", 1));
|
183 |
200 |
}
|
184 |
201 |
|
185 |
202 |
prevSize = columnNode.getValues().size();
|
186 |
203 |
|
187 |
204 |
if (!prevValues.isEmpty()) {
|
188 |
|
prevValues.remove(prevValues.size() - 1);
|
|
205 |
prevValues.remove(prevValues.size() - 1); // remove last value
|
189 |
206 |
}
|
190 |
207 |
}
|
191 |
208 |
}
|
... | ... | |
203 |
220 |
|
204 |
221 |
/**
|
205 |
222 |
* Gets original values of a given list.
|
206 |
|
* @param list list from which original values should be taken
|
207 |
|
* @return list of original values
|
|
223 |
* @param list List from which original values should be taken.
|
|
224 |
* @return List of original values.
|
208 |
225 |
*/
|
209 |
226 |
private List<String> getOriginalValuesFromList(List<String> list) {
|
210 |
227 |
List<String> origList = new ArrayList<>();
|
... | ... | |
220 |
237 |
|
221 |
238 |
/**
|
222 |
239 |
* Creates data rows.
|
223 |
|
* @return list of contingency table rows
|
|
240 |
* @return List of contingency table rows.
|
224 |
241 |
*/
|
225 |
242 |
private List<ContingencyTableRow> createDataRows() {
|
226 |
243 |
List<ContingencyTableRow> dataRows = new ArrayList<>();
|
... | ... | |
237 |
254 |
long stopTime = System.nanoTime();
|
238 |
255 |
System.out.println("Rows List:" + TimeUnit.MILLISECONDS.convert((stopTime - startTime), TimeUnit.NANOSECONDS));
|
239 |
256 |
|
|
257 |
// loop through all generated rows and store unusable rows to the list rowsToBeRemoved
|
240 |
258 |
List<ContingencyTableRow> rowsToBeRemoved = new ArrayList<>();
|
241 |
259 |
for (int i = 0; i < dataRows.size(); i++) {
|
242 |
260 |
if (!fillRowWithData(dataRows.get(i), rowNodes.get(i))) {
|
... | ... | |
244 |
262 |
}
|
245 |
263 |
}
|
246 |
264 |
|
|
265 |
// remove unusable rows
|
247 |
266 |
dataRows.removeAll(rowsToBeRemoved);
|
248 |
267 |
|
|
268 |
// create final row (row with total values of each column)
|
249 |
269 |
if (valueFunctions.get(0).getFunction() != null && (!valueFunctions.get(0).getFunction().equals("NIC") ||
|
250 |
270 |
(valueFunctions.get(0).getFunction().equals("NIC") && columnNames.size() > 0))) {
|
251 |
271 |
dataRows.add(createFinalRow());
|
... | ... | |
256 |
276 |
|
257 |
277 |
/**
|
258 |
278 |
* Recursively generates all possible row combinations, sorted as in contingency table.
|
259 |
|
* @param rows list of sorted contingency table rows
|
260 |
|
* @param index index in the values list
|
261 |
|
* @param values list of lists of values of each query row
|
262 |
|
* @param rowNodes list of row nodes
|
263 |
|
* @param prevNode parent node of the nodes
|
|
279 |
* @param rows List of sorted contingency table rows.
|
|
280 |
* @param index Index in the values list.
|
|
281 |
* @param values List of lists of values of each query row.
|
|
282 |
* @param rowNodes List of row nodes.
|
|
283 |
* @param prevNode Parent node of the nodes.
|
264 |
284 |
*/
|
265 |
285 |
private void generateRows(List<ContingencyTableRow> rows, int index, List<List<String>> values, List<Node> rowNodes,
|
266 |
286 |
Node prevNode) {
|
... | ... | |
268 |
288 |
List<String> list = values.get(index);
|
269 |
289 |
for (String s : list) {
|
270 |
290 |
StringBuilder levelString = new StringBuilder();
|
|
291 |
// add indent if row value has index higher than 0
|
271 |
292 |
for (int i = 0; i < index; i++) {
|
272 |
293 |
levelString.append(" ");
|
273 |
294 |
}
|
... | ... | |
276 |
297 |
row.addTableRowCell(new ContingencyTableRowCell(levelString.toString(), 1));
|
277 |
298 |
rows.add(row);
|
278 |
299 |
Node node = new Node(prevNode);
|
|
300 |
// save a value from a chosen row
|
279 |
301 |
node.getValues().add(s);
|
|
302 |
// visit (save) root
|
280 |
303 |
rowNodes.add(node);
|
281 |
304 |
int newIndex = index + 1;
|
|
305 |
// visit sub tree
|
282 |
306 |
generateRows(rows, newIndex, values, rowNodes, node);
|
283 |
307 |
}
|
284 |
308 |
}
|
... | ... | |
286 |
310 |
|
287 |
311 |
/**
|
288 |
312 |
* Recursively generates all possible column combinations, sorted as in contingency table.
|
289 |
|
* @param index index in the values list
|
290 |
|
* @param values list of lists of values of each query row
|
291 |
|
* @param columnNodes list of column nodes
|
292 |
|
* @param prevNode parent node of the nodes
|
|
313 |
* @param index Index in the values list.
|
|
314 |
* @param values List of lists of values of each query row.
|
|
315 |
* @param columnNodes List of column nodes.
|
|
316 |
* @param prevNode Parent node of the nodes.
|
293 |
317 |
*/
|
294 |
318 |
private void generateColumns(int index, List<List<String>> values, List<Node> columnNodes, Node prevNode) {
|
295 |
319 |
if (index < values.size()) {
|
296 |
320 |
List<String> list = values.get(index);
|
297 |
321 |
for (String s : list) {
|
298 |
322 |
Node node = new Node(prevNode);
|
|
323 |
// save a value from a chosen column
|
299 |
324 |
node.getValues().add(s);
|
300 |
325 |
if (isNotRemoveEmpty) {
|
301 |
326 |
int newIndex = index + 1;
|
|
327 |
// first visit all subtrees
|
302 |
328 |
generateColumns(newIndex, values, columnNodes, node);
|
|
329 |
// visit (save) root
|
303 |
330 |
columnNodes.add(node);
|
304 |
331 |
}
|
305 |
332 |
else if (checkIfColumnIsUsable(node.getValues())) {
|
306 |
333 |
int newIndex = index + 1;
|
|
334 |
// first visit all subtrees
|
307 |
335 |
generateColumns(newIndex, values, columnNodes, node);
|
|
336 |
// visit (save) root
|
308 |
337 |
columnNodes.add(node);
|
309 |
338 |
}
|
310 |
339 |
}
|
... | ... | |
313 |
342 |
|
314 |
343 |
/**
|
315 |
344 |
* Fills each data row with data.
|
316 |
|
* @param row row to ne filled with data
|
317 |
|
* @param node node of the row
|
|
345 |
* @param row Row to be filled with data.
|
|
346 |
* @param rowNode Node of the row.
|
318 |
347 |
*/
|
319 |
|
private boolean fillRowWithData(ContingencyTableRow row, Node node) {
|
|
348 |
private boolean fillRowWithData(ContingencyTableRow row, Node rowNode) {
|
320 |
349 |
if (valueFunctions.size() == 0) {
|
321 |
350 |
return true;
|
322 |
351 |
}
|
323 |
352 |
|
324 |
353 |
boolean isSingleValueRow = false;
|
325 |
354 |
|
326 |
|
if (node.getValues().size() <= 1) {
|
|
355 |
// check if row is a root (single) value
|
|
356 |
if (rowNode.getValues().size() <= 1) {
|
327 |
357 |
isSingleValueRow = true;
|
328 |
358 |
}
|
329 |
359 |
|
|
360 |
// stores if row is usable
|
330 |
361 |
boolean isRowUsable = false;
|
|
362 |
|
|
363 |
// if user selected an option to show all rows and columns, set that row is always usable
|
331 |
364 |
if (isNotRemoveEmpty) {
|
332 |
365 |
isRowUsable = true;
|
333 |
366 |
}
|
334 |
367 |
|
|
368 |
// if no columns or functions were selected
|
335 |
369 |
if (columnNodes.size() == 0) {
|
336 |
370 |
columnNodes.add(new Node());
|
337 |
371 |
}
|
338 |
372 |
|
339 |
|
List<Integer> usableIDs = getUsableIDs(node);
|
|
373 |
// load the list of usable original row IDs
|
|
374 |
List<Integer> usableIDs = getUsableIDs(rowNode.getValues());
|
340 |
375 |
|
341 |
376 |
if (valueFunctions.get(0).getFunction() != null && valueFunctions.get(0).getFunction().equals("NIC") &&
|
342 |
|
!usableIDs.isEmpty()) {
|
|
377 |
!usableIDs.isEmpty()) { // return that row is usable because it is used for list generation
|
343 |
378 |
return true;
|
344 |
379 |
}
|
345 |
380 |
else if (valueFunctions.get(0).getFunction() != null && valueFunctions.get(0).getFunction().equals("NIC") &&
|
346 |
|
usableIDs.isEmpty()) {
|
|
381 |
usableIDs.isEmpty()) { // no function selected and no usable rows in original return if row is usable
|
347 |
382 |
return isRowUsable;
|
348 |
383 |
}
|
349 |
384 |
|
|
385 |
// array of total values for functions
|
350 |
386 |
DoubleWrapper[] totals = new DoubleWrapper[valueFunctions.size()];
|
351 |
387 |
initializeDoubleWrapperField(totals);
|
352 |
388 |
|
|
389 |
// array of total sum values for functions if functions are AVG
|
353 |
390 |
DoubleWrapper[] totalsAvgSum = new DoubleWrapper[valueFunctions.size()];
|
354 |
391 |
initializeDoubleWrapperField(totalsAvgSum);
|
355 |
392 |
|
|
393 |
// array that stores if total value cell will be filled or left blank for current row and each function
|
356 |
394 |
boolean[] isFilledValueCells = new boolean[valueFunctions.size()];
|
357 |
|
//hodnota
|
|
395 |
// for each function
|
358 |
396 |
for (int v = 0; v < valueFunctions.size(); v++) {
|
|
397 |
// if function has not been selected
|
359 |
398 |
if (valueFunctions.get(v).getFunction() != null && (valueFunctions.get(v).getFunction().equals("") ||
|
360 |
399 |
valueFunctions.get(v).getFunction().equals("NIC"))) {
|
361 |
400 |
isRowUsable = true;
|
362 |
401 |
break;
|
363 |
402 |
}
|
|
403 |
|
|
404 |
// stores if first MIN or MAX total value was saved for current function
|
364 |
405 |
BooleanWrapper isFirstMinMaxTotal = new BooleanWrapper(true);
|
|
406 |
|
365 |
407 |
ValueFunction valueFunction = valueFunctions.get(v);
|
366 |
|
//sloupec v kont. tabulce
|
|
408 |
// for each contingency table column
|
367 |
409 |
for (Node columnNode : columnNodes) {
|
|
410 |
// result that will be stored in a cell given by row and column rowNode
|
368 |
411 |
DoubleWrapper result = new DoubleWrapper(0);
|
|
412 |
// sum result used to calculate AVG result in a cell given by row and column rowNode
|
369 |
413 |
DoubleWrapper resultAvgSum = new DoubleWrapper(0);
|
|
414 |
// stores if first MIN or MAX value was saved for current cell
|
370 |
415 |
BooleanWrapper isFirstMinMax = new BooleanWrapper(true);
|
|
416 |
// stores if a cell will be filled or left blank
|
371 |
417 |
boolean isFilledCell = false;
|
372 |
|
// radek v orig. tabulce
|
|
418 |
// for each usable row
|
373 |
419 |
for (Integer usableID : usableIDs) {
|
374 |
420 |
boolean isUsable = true;
|
|
421 |
// index of selected row
|
375 |
422 |
int j;
|
376 |
|
// zvoleny sloupec ze sloupcu, ziska hodnoty z pouzitelne radky danych sloupcu originalni tabulky a
|
377 |
|
// pokud se vsechny rovnaji hodnotam, ktere jsou ulozeny v hodnotach uzlu na pozici vybraneho
|
378 |
|
// sloupce, je kommbinace pouzitelna k vypoctum
|
|
423 |
// check if values of the contingency table column rowNode are present in the row (at usableID position
|
|
424 |
// of original table) for columns that belong to column rowNode
|
379 |
425 |
for (j = 0; j < columnNode.getValues().size(); j++) {
|
380 |
426 |
if (!tableColumns.get(columnNames.get(j).getName()).getValues().get(usableID).equals(columnNode.getValues().get(j))) {
|
381 |
427 |
isUsable = false;
|
... | ... | |
383 |
429 |
}
|
384 |
430 |
}
|
385 |
431 |
|
386 |
|
// zvoleny sloupec z hodnot
|
|
432 |
// selected column from value
|
387 |
433 |
if (tableColumns.get(valueFunction.getNameOfSelect()).getValues().get(usableID) == null) {
|
388 |
434 |
isUsable = false;
|
389 |
435 |
}
|
390 |
436 |
|
391 |
|
if (isUsable) { // pokud lze hodnotu pouzit, prunik vsech hodnot sedi (ma nejakou hodnotu)
|
|
437 |
// if value is usable, "intersect" of values from contingency table row and column, and value is true
|
|
438 |
if (isUsable) {
|
392 |
439 |
columnNode.setUsable(true);
|
393 |
440 |
isRowUsable = true;
|
394 |
441 |
isFilledCell = true;
|
395 |
442 |
computeValues(valueFunction, result, resultAvgSum, columnNode, isFirstMinMax,
|
396 |
443 |
usableID, false, isSingleValueRow);
|
|
444 |
// row is a root (single) value, save the result to the total function value cell
|
397 |
445 |
if (j <= 1) {
|
398 |
446 |
isFilledValueCells[v] = true;
|
399 |
447 |
computeValues(valueFunction, totals[v], totalsAvgSum[v], null, isFirstMinMaxTotal,
|
... | ... | |
401 |
449 |
}
|
402 |
450 |
}
|
403 |
451 |
}
|
|
452 |
// if cell should be blank, add empty value
|
404 |
453 |
if (!isFilledCell) {
|
405 |
454 |
row.addTableRowCell(new ContingencyTableRowCell("", 0));
|
406 |
455 |
}
|
407 |
|
else {
|
|
456 |
else { // generate a cell with a value
|
408 |
457 |
columnNode.setFilledTotalValue(true);
|
409 |
458 |
row.addTableRowCell(generateFilledCell(valueFunction.getFunction(), result.getValue(), result.getValue(), result.getValue(),
|
410 |
459 |
result.getValue(), resultAvgSum.getValue(), result.getValue()));
|
411 |
460 |
}
|
412 |
461 |
}
|
413 |
462 |
}
|
|
463 |
// generate cell for total function values
|
414 |
464 |
for (int i = 0; i < valueFunctions.size(); i++) {
|
415 |
465 |
if (valueFunctions.get(i).getFunction() != null && valueFunctions.get(i).getFunction().equals("NIC")) {
|
416 |
466 |
break;
|
417 |
467 |
}
|
|
468 |
// if cell should be blank, add empty value
|
418 |
469 |
if (!isFilledValueCells[i]) {
|
419 |
470 |
row.addTableRowCell(new ContingencyTableRowCell("", 0));
|
420 |
471 |
}
|
421 |
|
else {
|
|
472 |
else { // generate a cell with a value
|
422 |
473 |
valueFunctions.get(i).setFilledTotalValue(true);
|
423 |
474 |
row.addTableRowCell(generateFilledCell(valueFunctions.get(i).getFunction(), totals[i].getValue(), totals[i].getValue(),
|
424 |
475 |
totals[i].getValue(), totals[i].getValue(), totalsAvgSum[i].getValue(), totals[i].getValue()));
|
425 |
476 |
}
|
426 |
477 |
}
|
427 |
478 |
|
|
479 |
// returns if row should be visible in the contingency table
|
428 |
480 |
return isRowUsable;
|
429 |
481 |
}
|
430 |
482 |
|
431 |
483 |
/**
|
432 |
484 |
* Gets a list of IDs of the query rows that fit the contingency table row settings.
|
433 |
|
* @param node node of the row
|
434 |
|
* @return list of usable IDs
|
|
485 |
* @param rowNodeValues Values of a row node.
|
|
486 |
* @return List of usable row IDs.
|
435 |
487 |
*/
|
436 |
|
private List<Integer> getUsableIDs(Node node) {
|
|
488 |
private List<Integer> getUsableIDs(List<String> rowNodeValues) {
|
437 |
489 |
List<Integer> ids = new ArrayList<>();
|
438 |
490 |
|
|
491 |
// for each row in original table
|
439 |
492 |
for (int i = 0; i < tableColumns.get(rowNames.get(0).getName()).getValues().size(); i++) {
|
440 |
493 |
boolean isUsable = true;
|
441 |
|
for (int j = 0; j < node.getValues().size(); j++) {
|
442 |
|
if (!tableColumns.get(rowNames.get(j).getName()).getValues().get(i).equals(node.getValues().get(j))) {
|
|
494 |
// check if a row has values that are stored in the row node (for each chosen row)
|
|
495 |
for (int j = 0; j < rowNodeValues.size(); j++) {
|
|
496 |
if (!tableColumns.get(rowNames.get(j).getName()).getValues().get(i).equals(rowNodeValues.get(j))) {
|
443 |
497 |
isUsable = false;
|
444 |
498 |
break;
|
445 |
499 |
}
|
... | ... | |
458 |
512 |
* @return True if all values of a node are present in the original table columns.
|
459 |
513 |
*/
|
460 |
514 |
private boolean checkIfColumnIsUsable(List<String> columnNodeValues) {
|
|
515 |
// for each row in original table
|
461 |
516 |
for (int i = 0; i < tableColumns.get(columnNames.get(0).getName()).getValues().size(); i++) {
|
462 |
517 |
boolean isUsable = true;
|
|
518 |
// check if a row has values that are stored in the column node (for each chosen column)
|
463 |
519 |
for (int j = 0; j < columnNodeValues.size(); j++) {
|
464 |
520 |
if (!tableColumns.get(columnNames.get(j).getName()).getValues().get(i).equals(columnNodeValues.get(j))) {
|
465 |
521 |
isUsable = false;
|
... | ... | |
477 |
533 |
|
478 |
534 |
/**
|
479 |
535 |
* Computes value of the cell in regards to function.
|
480 |
|
* @param valueFunction Function that should be computed for a cell.
|
|
536 |
* @param valueFunction Column from which value should be taken and a function used and other info.
|
481 |
537 |
* @param result Variable to which result is saved.
|
482 |
538 |
* @param resultAvgSum Variable to which sum is saved of a function is AVG.
|
483 |
539 |
* @param columnNode Column node of a cell.
|
... | ... | |
559 |
615 |
|
560 |
616 |
/**
|
561 |
617 |
* Calculates COUNT function.
|
562 |
|
* @param valueFunction Function that should be computed for a cell.
|
|
618 |
* @param valueFunction Column from which value should be taken and other info.
|
563 |
619 |
* @param result Variable to which result is saved.
|
564 |
620 |
* @param columnNode Column node of a cell.
|
565 |
621 |
* @param isValueTotal Tells if a value is total value for the given function.
|
... | ... | |
578 |
634 |
|
579 |
635 |
/**
|
580 |
636 |
* Calculates SUM function.
|
581 |
|
* @param valueFunction Function that should be computed for a cell.
|
|
637 |
* @param valueFunction Column from which value should be taken and other info.
|
582 |
638 |
* @param result Variable to which result is saved.
|
583 |
639 |
* @param columnNode Column node of a cell.
|
584 |
640 |
* @param usableID ID of the row in the original table.
|
... | ... | |
588 |
644 |
private void sum(ValueFunction valueFunction, DoubleWrapper result, Node columnNode, int usableID, boolean isValueTotal,
|
589 |
645 |
boolean isSingleValueRow) {
|
590 |
646 |
if (valueFunction.getType().equals("Číslo")) {
|
591 |
|
result.setValue(result.getValue() + Double.parseDouble(tableColumns.get(valueFunction.getNameOfSelect()).getValues().get(usableID)));
|
|
647 |
double res = getDoubleValueFromTableCell(valueFunction, usableID);
|
|
648 |
result.setValue(result.getValue() + res);
|
592 |
649 |
if (columnNode != null && isSingleValueRow) {
|
593 |
|
columnNode.setTotalResultSum(columnNode.getTotalResultSum() + Double.parseDouble(tableColumns.get(valueFunction.getNameOfSelect()).getValues().get(usableID)));
|
|
650 |
columnNode.setTotalResultSum(columnNode.getTotalResultSum() + res);
|
594 |
651 |
}
|
595 |
652 |
if (isValueTotal && isSingleValueRow) {
|
596 |
|
valueFunction.setTotalResultSum(valueFunction.getTotalResultSum() + Double.parseDouble(tableColumns.get(valueFunction.getNameOfSelect()).getValues().get(usableID)));
|
|
653 |
valueFunction.setTotalResultSum(valueFunction.getTotalResultSum() + res);
|
597 |
654 |
}
|
598 |
655 |
}
|
599 |
656 |
}
|
600 |
657 |
|
601 |
658 |
/**
|
602 |
659 |
* Calculates MIN function.
|
603 |
|
* @param valueFunction Function that should be computed for a cell.
|
|
660 |
* @param valueFunction Column from which value should be taken and other info.
|
604 |
661 |
* @param result Variable to which result is saved.
|
605 |
662 |
* @param columnNode Column node of a cell.
|
606 |
663 |
* @param isFirstMinMax Tells if the counted value is the first value of the MIN or MAX function.
|
... | ... | |
611 |
668 |
private void min(ValueFunction valueFunction, DoubleWrapper result, Node columnNode, BooleanWrapper isFirstMinMax,
|
612 |
669 |
int usableID, boolean isValueTotal, boolean isSingleValueRow) {
|
613 |
670 |
if (valueFunction.getType().equals("Číslo")) {
|
|
671 |
double res = getDoubleValueFromTableCell(valueFunction, usableID);
|
|
672 |
// if min value of the cell has not been stored yet
|
614 |
673 |
if (isFirstMinMax.isValue()) {
|
615 |
674 |
isFirstMinMax.setValue(false);
|
616 |
|
result.setValue(Double.parseDouble(tableColumns.get(valueFunction.getNameOfSelect()).getValues().get(usableID)));
|
|
675 |
result.setValue(res);
|
617 |
676 |
}
|
618 |
677 |
else {
|
619 |
|
result.setValue(Math.min(result.getValue(), Integer.parseInt(tableColumns.get(valueFunction.getNameOfSelect()).getValues().get(usableID))));
|
|
678 |
result.setValue(Math.min(result.getValue(), res));
|
620 |
679 |
}
|
621 |
680 |
if (columnNode != null && isSingleValueRow) {
|
|
681 |
// if min value of the entire column has not been stored yet
|
622 |
682 |
if (columnNode.isFirstMin()) {
|
623 |
683 |
columnNode.setFirstMin(false);
|
624 |
|
columnNode.setTotalMin(Double.parseDouble(tableColumns.get(valueFunction.getNameOfSelect()).getValues().get(usableID)));
|
|
684 |
columnNode.setTotalMin(res);
|
625 |
685 |
} else {
|
626 |
|
columnNode.setTotalMin(Math.min(columnNode.getTotalMin(), Integer.parseInt(tableColumns.get(valueFunction.getNameOfSelect()).getValues().get(usableID))));
|
|
686 |
columnNode.setTotalMin(Math.min(columnNode.getTotalMin(), res));
|
627 |
687 |
}
|
628 |
688 |
}
|
629 |
689 |
if (isValueTotal && isSingleValueRow) {
|
|
690 |
// if min value of the entire value column has not been stored yet
|
630 |
691 |
if (valueFunction.isFirstMin()) {
|
631 |
692 |
valueFunction.setFirstMin(false);
|
632 |
|
valueFunction.setTotalMin(Double.parseDouble(tableColumns.get(valueFunction.getNameOfSelect()).getValues().get(usableID)));
|
|
693 |
valueFunction.setTotalMin(res);
|
633 |
694 |
} else {
|
634 |
|
valueFunction.setTotalMin(Math.min(valueFunction.getTotalMin(), Integer.parseInt(tableColumns.get(valueFunction.getNameOfSelect()).getValues().get(usableID))));
|
|
695 |
valueFunction.setTotalMin(Math.min(valueFunction.getTotalMin(), res));
|
635 |
696 |
}
|
636 |
697 |
}
|
637 |
698 |
}
|
... | ... | |
639 |
700 |
|
640 |
701 |
/**
|
641 |
702 |
* Calculates MAX function.
|
642 |
|
* @param valueFunction Function that should be computed for a cell.
|
|
703 |
* @param valueFunction Column from which value should be taken and other info.
|
643 |
704 |
* @param result Variable to which result is saved.
|
644 |
705 |
* @param columnNode Column node of a cell.
|
645 |
706 |
* @param isFirstMinMax Tells if the counted value is the first value of the MIN or MAX function.
|
... | ... | |
650 |
711 |
private void max(ValueFunction valueFunction, DoubleWrapper result, Node columnNode, BooleanWrapper isFirstMinMax,
|
651 |
712 |
int usableID, boolean isValueTotal, boolean isSingleValueRow) {
|
652 |
713 |
if (valueFunction.getType().equals("Číslo")) {
|
|
714 |
double res = getDoubleValueFromTableCell(valueFunction, usableID);
|
653 |
715 |
if (isFirstMinMax.isValue()) {
|
|
716 |
// if max value of the cell has not been stored yet
|
654 |
717 |
isFirstMinMax.setValue(false);
|
655 |
|
result.setValue(Double.parseDouble(tableColumns.get(valueFunction.getNameOfSelect()).getValues().get(usableID)));
|
|
718 |
result.setValue(res);
|
656 |
719 |
}
|
657 |
720 |
else {
|
658 |
|
result.setValue(Math.max(result.getValue(), Integer.parseInt(tableColumns.get(valueFunction.getNameOfSelect()).getValues().get(usableID))));
|
|
721 |
result.setValue(Math.max(result.getValue(), res));
|
659 |
722 |
}
|
660 |
723 |
if (columnNode != null && isSingleValueRow) {
|
|
724 |
// if max value of the entire column has not been stored yet
|
661 |
725 |
if (columnNode.isFirstMax()) {
|
662 |
726 |
columnNode.setFirstMax(false);
|
663 |
|
columnNode.setTotalMax(Double.parseDouble(tableColumns.get(valueFunction.getNameOfSelect()).getValues().get(usableID)));
|
|
727 |
columnNode.setTotalMax(res);
|
664 |
728 |
} else {
|
665 |
|
columnNode.setTotalMax(Math.max(columnNode.getTotalMax(), Integer.parseInt(tableColumns.get(valueFunction.getNameOfSelect()).getValues().get(usableID))));
|
|
729 |
columnNode.setTotalMax(Math.max(columnNode.getTotalMax(), res));
|
666 |
730 |
}
|
667 |
731 |
}
|
668 |
732 |
if (isValueTotal && isSingleValueRow) {
|
|
733 |
// if max value of the entire value column has not been stored yet
|
669 |
734 |
if (valueFunction.isFirstMax()) {
|
670 |
735 |
valueFunction.setFirstMax(false);
|
671 |
|
valueFunction.setTotalMax(Double.parseDouble(tableColumns.get(valueFunction.getNameOfSelect()).getValues().get(usableID)));
|
|
736 |
valueFunction.setTotalMax(res);
|
672 |
737 |
} else {
|
673 |
|
valueFunction.setTotalMax(Math.max(valueFunction.getTotalMax(), Integer.parseInt(tableColumns.get(valueFunction.getNameOfSelect()).getValues().get(usableID))));
|
|
738 |
valueFunction.setTotalMax(Math.max(valueFunction.getTotalMax(), res));
|
674 |
739 |
}
|
675 |
740 |
}
|
676 |
741 |
}
|
... | ... | |
678 |
743 |
|
679 |
744 |
/**
|
680 |
745 |
* Calculates AVG function.
|
681 |
|
* @param valueFunction Function that should be computed for a cell.
|
|
746 |
* @param valueFunction Column from which value should be taken and other info.
|
682 |
747 |
* @param result Variable to which count result is saved.
|
683 |
748 |
* @param resultAvgSum Variable to which sum result is saved.
|
684 |
749 |
* @param columnNode Column node of a cell.
|
... | ... | |
689 |
754 |
private void average(ValueFunction valueFunction, DoubleWrapper result, DoubleWrapper resultAvgSum, Node columnNode,
|
690 |
755 |
int usableID, boolean isValueTotal, boolean isSingleValueRow) {
|
691 |
756 |
if (valueFunction.getType().equals("Číslo")) {
|
|
757 |
double res = getDoubleValueFromTableCell(valueFunction, usableID);
|
692 |
758 |
result.setValue(result.getValue() + 1);
|
693 |
|
resultAvgSum.setValue(resultAvgSum.getValue() + Double.parseDouble(tableColumns.get(valueFunction.getNameOfSelect()).getValues().get(usableID)));
|
|
759 |
resultAvgSum.setValue(resultAvgSum.getValue() + res);
|
694 |
760 |
if (columnNode != null && isSingleValueRow) {
|
695 |
761 |
columnNode.setTotalResultAvg(columnNode.getTotalResultAvg() + 1);
|
696 |
|
columnNode.setTotalResultAvgSum(columnNode.getTotalResultAvgSum() + Double.parseDouble(tableColumns.get(valueFunction.getNameOfSelect()).getValues().get(usableID)));
|
|
762 |
columnNode.setTotalResultAvgSum(columnNode.getTotalResultAvgSum() + res);
|
697 |
763 |
}
|
698 |
764 |
if (isValueTotal && isSingleValueRow) {
|
699 |
765 |
valueFunction.setTotalResultAvg(valueFunction.getTotalResultAvg() + 1);
|
700 |
|
valueFunction.setTotalResultAvgSum(valueFunction.getTotalResultAvgSum() + Double.parseDouble(tableColumns.get(valueFunction.getNameOfSelect()).getValues().get(usableID)));
|
|
766 |
valueFunction.setTotalResultAvgSum(valueFunction.getTotalResultAvgSum() + res);
|
701 |
767 |
}
|
702 |
768 |
}
|
703 |
769 |
}
|
704 |
770 |
|
|
771 |
/**
|
|
772 |
* Gets double value from a cell in a value column and usableID row in an original table
|
|
773 |
* @param valueFunction Column from which value should be taken and other info.
|
|
774 |
* @param usableID ID of the row in the original table.
|
|
775 |
* @return Parsed double value.
|
|
776 |
*/
|
|
777 |
private double getDoubleValueFromTableCell(ValueFunction valueFunction, int usableID) {
|
|
778 |
double res;
|
|
779 |
try {
|
|
780 |
res = Double.parseDouble(tableColumns.get(valueFunction.getNameOfSelect()).getValues().get(usableID));
|
|
781 |
}
|
|
782 |
catch (Exception e) {
|
|
783 |
res = Double.NaN;
|
|
784 |
}
|
|
785 |
|
|
786 |
return res;
|
|
787 |
}
|
|
788 |
|
705 |
789 |
/**
|
706 |
790 |
* Generates a final row, with total values of columns.
|
707 |
791 |
* @return Final row filled with data.
|
... | ... | |
715 |
799 |
}
|
716 |
800 |
|
717 |
801 |
List<ContingencyTableRowCell> valueCells = new ArrayList<>();
|
|
802 |
// for each selected function
|
718 |
803 |
for (ValueFunction valueFunction : valueFunctions) {
|
|
804 |
//for each column
|
719 |
805 |
for (Node columnNode : columnNodes) {
|
720 |
806 |
if (columnNode.isFilledTotalValue()) {
|
721 |
807 |
finalRow.addTableRowCell(generateFilledCell(valueFunction.getFunction(), columnNode.getTotalResult(), columnNode.getTotalResultSum(),
|
... | ... | |
736 |
822 |
}
|
737 |
823 |
}
|
738 |
824 |
|
|
825 |
// append value cells to the end
|
739 |
826 |
finalRow.addTableRowCells(valueCells);
|
740 |
827 |
|
741 |
828 |
return finalRow;
|
re #8176 nothing; re #8178 added checks for data types; added table name to the generated table