414 lines
14 KiB
Java
414 lines
14 KiB
Java
package de.wwwu.awolf.view.panels;
|
|
|
|
import de.wwwu.awolf.model.Line;
|
|
import de.wwwu.awolf.presenter.Presenter;
|
|
import de.wwwu.awolf.presenter.algorithms.Algorithm;
|
|
import de.wwwu.awolf.presenter.data.DataProvider;
|
|
import de.wwwu.awolf.presenter.util.Logging;
|
|
import de.wwwu.awolf.view.MainFrame;
|
|
import de.wwwu.awolf.view.custom.ButtonGroupAtLeastTwo;
|
|
|
|
import javax.swing.*;
|
|
import javax.swing.border.TitledBorder;
|
|
import javax.swing.filechooser.FileNameExtensionFilter;
|
|
import javax.swing.filechooser.FileSystemView;
|
|
import javax.swing.table.DefaultTableModel;
|
|
import javax.swing.table.JTableHeader;
|
|
import java.awt.*;
|
|
import java.io.File;
|
|
import java.io.Serializable;
|
|
import java.util.List;
|
|
import java.util.*;
|
|
|
|
/**
|
|
* Created by
|
|
* Armin Wolf
|
|
* on 02.08.17.
|
|
*/
|
|
public class EvaluationPanel extends JPanel {
|
|
|
|
private final MainFrame view;
|
|
private JTable table;
|
|
private JTableHeader header;
|
|
private JButton start;
|
|
private JButton clearTable;
|
|
private JButton exportData;
|
|
private JRadioButton evalTypeOne; //1: Alg - N: Data
|
|
private JRadioButton evalTypeTwo; //N: Alg - 1: Data
|
|
private ButtonGroup radiobuttonGroup;
|
|
private ButtonGroup checkboxGroup;
|
|
private ButtonGroupAtLeastTwo checkboxAtLeastOne;
|
|
|
|
private JCheckBox lms; //1: Alg - N: Data
|
|
private JCheckBox rm; //N: Alg - 1: Data
|
|
private JCheckBox ts; //1: Alg - N: Data
|
|
|
|
private JPanel comp;
|
|
private JPanel algorithmPanel;
|
|
private JPanel leftSidePanel;
|
|
private JPanel datasetCount;
|
|
private JComboBox<Integer> datasetCountChoice;
|
|
private JComboBox<String> datasetType;
|
|
private JLabel datasetCountLabel;
|
|
|
|
private JSplitPane splitPane;
|
|
|
|
private DefaultTableModel model;
|
|
private int currentRowOfTypes;
|
|
private JPanel buttonPanel;
|
|
private PlotPanel plotPanel;
|
|
private Map<Algorithm.Type, Color> colorMap;
|
|
private String[] selections = {"Approximationsgüte", "Least Median of Squares", "Repeated-Median", "Theil-Sen"};
|
|
|
|
/**
|
|
* Konstruktor
|
|
*
|
|
* @param view View
|
|
*/
|
|
public EvaluationPanel(MainFrame view) {
|
|
super();
|
|
this.view = view;
|
|
this.setLayout(new BorderLayout());
|
|
this.currentRowOfTypes = 0;
|
|
this.colorMap = new HashMap<>();
|
|
this.colorMap.put(Algorithm.Type.LMS, Color.ORANGE);
|
|
this.colorMap.put(Algorithm.Type.RM, Color.RED);
|
|
this.colorMap.put(Algorithm.Type.TS, Color.MAGENTA);
|
|
this.colorMap.put(Algorithm.Type.NAIV_LMS, Color.BLUE);
|
|
this.colorMap.put(Algorithm.Type.NAIV_RM, Color.GREEN);
|
|
this.colorMap.put(Algorithm.Type.NAIV_TS, Color.CYAN);
|
|
|
|
init();
|
|
addListener();
|
|
addComponents();
|
|
|
|
}
|
|
|
|
/**
|
|
* Initialisiere die Komponenten
|
|
*/
|
|
private void init() {
|
|
datasetCountLabel = new JLabel("Größe des Datensatzes");
|
|
Integer[] choice = {50, 100, 200, 500, 1000, 1500};
|
|
datasetCountChoice = new JComboBox(choice);
|
|
String[] datatypes = {"Punktwolke", "Gerade", "Kreis und Gerade", "Import von CSV-Datei"};
|
|
datasetType = new JComboBox<>(datatypes);
|
|
|
|
start = new JButton("Start");
|
|
clearTable = new JButton("Löschen");
|
|
exportData = new JButton("Datenexport");
|
|
clearTable.setEnabled(false);
|
|
exportData.setEnabled(false);
|
|
evalTypeOne = new JRadioButton("Algorithmus evaluieren");
|
|
evalTypeTwo = new JRadioButton("Algorithmen vergleichen");
|
|
lms = new JCheckBox("Least Median of Squares");
|
|
rm = new JCheckBox("Repeated Median");
|
|
ts = new JCheckBox("Theil-Sen");
|
|
radiobuttonGroup = new ButtonGroup();
|
|
checkboxGroup = new ButtonGroup();
|
|
checkboxAtLeastOne = new ButtonGroupAtLeastTwo();
|
|
buttonPanel = new JPanel(new FlowLayout());
|
|
leftSidePanel = new JPanel(new BorderLayout());
|
|
comp = new JPanel(new GridLayout(0, 1));
|
|
plotPanel = new PlotPanel();
|
|
model = new DefaultTableModel() {
|
|
@Override
|
|
public boolean isCellEditable(int row, int column) {
|
|
//all cells false
|
|
return false;
|
|
}
|
|
};
|
|
table = new JTable(model);
|
|
UIManager.put("TableHeader.font", new Font("SansSerif", Font.BOLD, 14));
|
|
UIManager.put("TableHeader.foreground", Color.WHITE);
|
|
header = table.getTableHeader();
|
|
header.setBackground(Color.GRAY);
|
|
|
|
splitPane = new JSplitPane();
|
|
algorithmPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
|
|
datasetCount = new JPanel(new FlowLayout(FlowLayout.LEFT));
|
|
|
|
}
|
|
|
|
/**
|
|
* Hinzufügen der Komponenten zum ContentPane
|
|
*/
|
|
private void addComponents() {
|
|
evalTypeOne.setSelected(true);
|
|
lms.setSelected(true);
|
|
checkboxGroup.add(lms);
|
|
checkboxGroup.add(rm);
|
|
checkboxGroup.add(ts);
|
|
|
|
radiobuttonGroup.add(evalTypeOne);
|
|
radiobuttonGroup.add(evalTypeTwo);
|
|
|
|
buttonPanel.add(start);
|
|
buttonPanel.add(clearTable);
|
|
buttonPanel.add(exportData);
|
|
|
|
algorithmPanel.add(lms);
|
|
algorithmPanel.add(rm);
|
|
algorithmPanel.add(ts);
|
|
|
|
datasetCount.add(datasetCountLabel);
|
|
datasetCount.add(datasetCountChoice);
|
|
datasetCount.add(datasetType);
|
|
|
|
comp.add(evalTypeOne);
|
|
comp.add(evalTypeTwo);
|
|
comp.add(algorithmPanel);
|
|
comp.add(datasetCount);
|
|
|
|
comp.setBorder(new TitledBorder("Konfiguration"));
|
|
|
|
//Tabelle
|
|
table.setDragEnabled(true);
|
|
JScrollPane scrollPane = new JScrollPane(table);
|
|
scrollPane.setWheelScrollingEnabled(true);
|
|
scrollPane.setBorder(new TitledBorder("Ergebnisse"));
|
|
|
|
|
|
//Plot
|
|
plotPanel.createPlot(new LinkedList<>());
|
|
plotPanel.setBorder(new TitledBorder("Plot"));
|
|
|
|
leftSidePanel.add(comp, BorderLayout.NORTH);
|
|
leftSidePanel.add(scrollPane, BorderLayout.CENTER);
|
|
|
|
//Splitpane
|
|
splitPane.setOrientation(JSplitPane.HORIZONTAL_SPLIT);
|
|
splitPane.setResizeWeight(.5d);
|
|
splitPane.setContinuousLayout(true);
|
|
splitPane.setLeftComponent(leftSidePanel);
|
|
splitPane.setRightComponent(plotPanel);
|
|
|
|
this.add(splitPane, BorderLayout.CENTER);
|
|
|
|
this.add(buttonPanel, BorderLayout.SOUTH);
|
|
|
|
}
|
|
|
|
/**
|
|
* Hinzufügen der Listener
|
|
*/
|
|
private void addListener() {
|
|
start.addActionListener(e -> {
|
|
int type;
|
|
int alg;
|
|
int n;
|
|
if (radiobuttonGroup.isSelected(evalTypeOne.getModel())) {
|
|
type = 0;
|
|
} else {
|
|
type = 1;
|
|
}
|
|
alg = checkSelection();
|
|
n = (Integer) datasetCountChoice.getSelectedItem();
|
|
String datatyp = (String) datasetType.getSelectedItem();
|
|
if ("Import von CSV-Datei".equals(datatyp)) {
|
|
SwingUtilities.invokeLater(() -> {
|
|
File file = null;
|
|
JFileChooser chooser = new JFileChooser(FileSystemView.getFileSystemView().getHomeDirectory());
|
|
chooser.setPreferredSize(new Dimension(800, 700));
|
|
chooser.setFileFilter(new FileNameExtensionFilter("Comma-Separated Value, (*.csv)", "csv", "text"));
|
|
|
|
chooser.setMultiSelectionEnabled(false);
|
|
chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
|
|
|
|
if (chooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
|
|
//Logging.logInfo ("Datei "+chooser.getSelectedFile()+ " ausgewählt.");
|
|
file = chooser.getSelectedFile();
|
|
final File input = file;
|
|
Thread t = new Thread(() -> ((Presenter) view.getPresenter()).startEvaluation(type, alg, input));
|
|
t.start();
|
|
}
|
|
});
|
|
|
|
} else {
|
|
((Presenter) view.getPresenter()).startEvaluation(type, n, alg, DataProvider.DataType.values()[datasetType.getSelectedIndex()]);
|
|
}
|
|
clearTable.setEnabled(true);
|
|
exportData.setEnabled(true);
|
|
});
|
|
|
|
evalTypeOne.addActionListener(e -> {
|
|
checkboxAtLeastOne.remove(lms);
|
|
checkboxAtLeastOne.remove(rm);
|
|
checkboxAtLeastOne.remove(ts);
|
|
lms.setSelected(true);
|
|
|
|
checkboxGroup.add(lms);
|
|
checkboxGroup.add(rm);
|
|
checkboxGroup.add(ts);
|
|
});
|
|
|
|
evalTypeTwo.addActionListener(e -> {
|
|
checkboxGroup.remove(lms);
|
|
checkboxGroup.remove(rm);
|
|
checkboxGroup.remove(ts);
|
|
|
|
checkboxAtLeastOne.addAll(lms, rm, ts);
|
|
|
|
lms.setSelected(true);
|
|
rm.setSelected(true);
|
|
});
|
|
|
|
clearTable.addActionListener(e -> {
|
|
SwingUtilities.invokeLater(() -> {
|
|
int n = model.getDataVector().size();
|
|
for (int i = 0; i < n; i++) {
|
|
model.removeRow(0);
|
|
currentRowOfTypes--;
|
|
}
|
|
this.revalidate();
|
|
clearTable.setEnabled(false);
|
|
exportData.setEnabled(false);
|
|
});
|
|
});
|
|
|
|
|
|
exportData.addActionListener(e -> {
|
|
SwingUtilities.invokeLater(() -> {
|
|
SwingUtilities.invokeLater(() -> {
|
|
File file = null;
|
|
JFileChooser chooser = new JFileChooser(FileSystemView.getFileSystemView().getHomeDirectory());
|
|
chooser.setPreferredSize(new Dimension(800, 700));
|
|
chooser.setFileFilter(new FileNameExtensionFilter("Comma-Separated Value, (*.csv)", "csv", "text"));
|
|
|
|
chooser.setMultiSelectionEnabled(false);
|
|
chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
|
|
|
|
|
|
if (chooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
|
|
file = chooser.getSelectedFile();
|
|
String filename = file.getAbsolutePath().contains(".csv") ? file.getAbsolutePath() : file.getAbsolutePath().concat(".csv");
|
|
final File input = new File(filename);
|
|
Thread t = new Thread(() -> ((Presenter) view.getPresenter()).startDatasetExportEvaluation(input));
|
|
t.start();
|
|
}
|
|
});
|
|
});
|
|
});
|
|
|
|
|
|
}
|
|
|
|
/**
|
|
* Fügt der Tabelle eine Spalte hinzu
|
|
*
|
|
* @param data Daten der Spalte
|
|
* @param col Spalte
|
|
* @param isLabel <code>true</code>, falls es sich um die Approximations Überschriften handelt
|
|
*/
|
|
public void addColumn(final List<? extends Serializable> data, final int col, final boolean isLabel) {
|
|
if (isLabel) {
|
|
addBlankRows(data.size());
|
|
}
|
|
|
|
for (int i = 0; i < data.size(); i++) {
|
|
int row = currentRowOfTypes - data.size() + i;
|
|
model.setValueAt(data.get(i), row, col);
|
|
}
|
|
this.repaint();
|
|
this.revalidate();
|
|
}
|
|
|
|
/**
|
|
* Fügt der Tabelle eine Zeile hinzu
|
|
*
|
|
* @param tableEntries Daten der Tabelle
|
|
*/
|
|
public void addRow(Map<Algorithm.Type, Map<String, String>> tableEntries) {
|
|
|
|
SwingUtilities.invokeLater(() -> {
|
|
|
|
Set<Algorithm.Type> types = tableEntries.keySet();
|
|
List<String> columnlabels = new ArrayList<>();
|
|
|
|
types.forEach(type -> {
|
|
columnlabels.add(" ");
|
|
});
|
|
model.setColumnIdentifiers(columnlabels.toArray());
|
|
tableEntries.entrySet().forEach(row -> {
|
|
model.addRow(row.getValue().keySet().toArray());
|
|
model.addRow(row.getValue().values().toArray());
|
|
});
|
|
|
|
this.repaint();
|
|
this.revalidate();
|
|
});
|
|
}
|
|
|
|
|
|
/**
|
|
* <p>
|
|
* Visualisierung der Ausgleichsgerade
|
|
*
|
|
* @param lines the lines
|
|
* @param alg identifizierung des Alg.
|
|
*/
|
|
public void drawLines(final List<Line> lines, final Algorithm.Type alg) {
|
|
for (Line line : lines) {
|
|
plotPanel.addLineToPlot(line.getM(), line.getB(), colorMap.get(alg), alg.name());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Visualisierung der dualen Geraden (Eingabemenge)
|
|
*
|
|
* @param points Liste der Geraden
|
|
*/
|
|
public void setDualPoints(List<Line> points) {
|
|
plotPanel = new PlotPanel();
|
|
plotPanel.setBorder(new TitledBorder("Plot"));
|
|
splitPane.setRightComponent(plotPanel);
|
|
plotPanel.createPlot(points);
|
|
plotPanel.repaint();
|
|
plotPanel.revalidate();
|
|
}
|
|
|
|
/**
|
|
* Hilfsmethode
|
|
*
|
|
* @param n Anzahl der leeren Zeilen
|
|
*/
|
|
private void addBlankRows(int n) {
|
|
for (int i = 0; i < n; i++) {
|
|
String[] tmp = {"", "", "", "",};
|
|
model.addRow(tmp);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Hilfsmethode
|
|
*
|
|
* @param val Anzahl der Zeilen die noch hinzugefügt werden
|
|
*/
|
|
public void setCurrentRow(int val) {
|
|
this.currentRowOfTypes += val;
|
|
}
|
|
|
|
/**
|
|
* @return Kodierung welche Algorithmen ausgewählt wurden
|
|
*/
|
|
private int checkSelection() {
|
|
if (lms.isSelected() && rm.isSelected() && ts.isSelected()) {
|
|
return 6;
|
|
} else if (!lms.isSelected() && rm.isSelected() && ts.isSelected()) {
|
|
return 5;
|
|
} else if (lms.isSelected() && !rm.isSelected() && ts.isSelected()) {
|
|
return 4;
|
|
} else if (lms.isSelected() && rm.isSelected() && !ts.isSelected()) {
|
|
return 3;
|
|
} else if (!lms.isSelected() && !rm.isSelected() && ts.isSelected()) {
|
|
return 2;
|
|
} else if (!lms.isSelected() && rm.isSelected() && !ts.isSelected()) {
|
|
return 1;
|
|
} else if (lms.isSelected() && !rm.isSelected() && !ts.isSelected()) {
|
|
return 0;
|
|
} else {
|
|
throw new IllegalStateException("Mindestens ein Algortihmus muss selektiert werden");
|
|
}
|
|
}
|
|
}
|