adjusted gui, adjusted line and point model classes

master
Armin Wolf 4 years ago
parent 59b4567d9e
commit 2c97aa1fe8

6
.gitattributes vendored

@ -0,0 +1,6 @@
#
# https://help.github.com/articles/dealing-with-line-endings/
#
# These are explicitly windows files and should use crlf
*.bat text eol=crlf

@ -8,6 +8,7 @@ plugins {
repositories {
mavenLocal()
mavenCentral()
maven {
url = uri('http://repo.maven.apache.org/maven2')
}
@ -21,6 +22,7 @@ dependencies {
implementation 'com.opencsv:opencsv:5.1'
implementation 'com.google.guava:guava:28.2-jre'
implementation 'org.powermock:powermock-core:2.0.6'
compile group: 'org.apache.commons', name: 'commons-math3', version: '3.6.1'
}
group = 'de.wwu.awolf'

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -1,5 +1,4 @@
/*
* This file was generated by the Gradle 'init' task.
*/
rootProject.name = 'masterarbeit'

@ -51,9 +51,13 @@ public class App extends Application {
//register at presenter
new GuiRegisterService(fxmlLoader.getController()).start();
primaryStage.setTitle(TITLE);
Scene scene = new Scene(pane, 1000, 800);
scene.getStylesheets().add(ViewController.class.getResource("/style/console.css").toExternalForm());
Scene scene = new Scene(pane, 1200, 900);
scene.getStylesheets().add(ViewController.class.getResource("/style/style.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.setOnCloseRequest(e -> {
Platform.exit();
System.exit(0);
});
primaryStage.show();
} catch (IOException e) {
Logging.logError("Error reading FXML file. ", e);

@ -1,5 +1,9 @@
package de.wwwu.awolf.model;
import org.apache.commons.math3.util.Precision;
import java.util.Objects;
/**
* Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden.
*
@ -9,6 +13,8 @@ package de.wwwu.awolf.model;
*/
public class Line implements Comparable<Line> {
private final double epsilon = 0.00001;
private final Double MAX = 9999d;
private final Double MIN = -9999d;
@ -76,20 +82,20 @@ public class Line implements Comparable<Line>{
}
private Double calculateX1(Double min) {
public Double calculateX1(Double min) {
return min;
}
private Double calculateY1(Double min) {
return (min * m) + b;
public Double calculateY1(Double min) {
return (min * (m * -1)) + b;
}
private Double calculateX2(Double max) {
public Double calculateX2(Double max) {
return max;
}
private Double calculateY2(Double max) {
return (max * m) + b;
public Double calculateY2(Double max) {
return (max * (m * -1)) + b;
}
/**
@ -189,7 +195,7 @@ public class Line implements Comparable<Line>{
public boolean equals(Object obj) {
if (obj instanceof Line) {
Line other = (Line) obj;
return other.getM().equals(this.getM()) && other.getB().equals(this.getB());
return Precision.equals(other.getM(), this.getM(), epsilon) && Precision.equals(other.getB(), this.getB(), epsilon);
} else {
return super.equals(obj);
}
@ -197,7 +203,7 @@ public class Line implements Comparable<Line>{
@Override
public int hashCode() {
return super.hashCode() + this.getM().hashCode() + this.getB().hashCode();
return Objects.hash(Precision.round(m, 5), Precision.round(b, 5));
}
@Override
@ -272,16 +278,10 @@ public class Line implements Comparable<Line>{
@Override
public int compareTo(Line line) {
if (this.getM().equals(line.getM())) {
if (this.getB() <= line.getB()) {
return -1;
} else {
return 1;
}
} else if (this.getM() < line.getM()) {
return -1;
if (Precision.compareTo(this.getM(), line.getM(), epsilon) == 0) {
return this.getB().compareTo(line.getB());
} else {
return 1;
return this.getM().compareTo(line.getM());
}
}
}

@ -17,6 +17,8 @@ public class LineModel {
private Double xMaximum;
private Double yMinimum;
private Double yMaximum;
private Double MIN;
private Double MAX;
private int size;
/**
@ -31,6 +33,8 @@ public class LineModel {
yMinimum = Double.MAX_VALUE;
yMaximum = Double.MIN_VALUE;
MIN = 0d;
MAX = 0d;
}
@ -41,8 +45,17 @@ public class LineModel {
*/
public void addLine(Line line) {
this.lines.add(line);
MIN = line.getM() <= MIN ? line.getM() : MIN;
MAX = line.getM() >= MAX ? line.getM() : MAX;
}
public Double getMIN() {
return MIN;
}
public Double getMAX() {
return MAX;
}
/**
* @return Liste der Geraden
@ -55,7 +68,7 @@ public class LineModel {
* @param lines Liste der Geraden
*/
public void setLines(Set<Line> lines) {
this.lines = lines;
lines.forEach(this::addLine);
this.size = lines.size();
}

@ -1,5 +1,9 @@
package de.wwwu.awolf.model;
import org.apache.commons.math3.util.Precision;
import java.util.Objects;
/**
* Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden.
*
@ -9,6 +13,8 @@ package de.wwwu.awolf.model;
*/
public class Point implements Comparable<Point> {
private final double epsilon = 0.00001;
private Double x;
private Double y;
private String id;
@ -67,16 +73,10 @@ public class Point implements Comparable<Point> {
@Override
public int compareTo(Point o) {
if (this.getX().equals(o.getX())) {
if (this.getY() <= o.getY()) {
return -1;
} else {
return 1;
}
} else if (this.getX() < o.getX()) {
return -1;
if (Precision.compareTo(this.getX(), o.getX(), epsilon) == 0) {
return this.getY().compareTo(o.getY());
} else {
return 1;
return this.getX().compareTo(o.getX());
}
}
@ -90,7 +90,7 @@ public class Point implements Comparable<Point> {
public boolean equals(Object obj) {
if (obj instanceof Point) {
Point other = (Point) obj;
return other.getX().equals(this.getX()) && other.getY().equals(this.getY());
return Precision.equals(other.getX(), this.getX(), epsilon) && Precision.equals(other.getY(), this.getY(), epsilon);
} else {
return super.equals(obj);
}
@ -98,7 +98,7 @@ public class Point implements Comparable<Point> {
@Override
public int hashCode() {
return super.hashCode() + this.getX().hashCode() + this.getY().hashCode();
return Objects.hash(Precision.round(x, 5), Precision.round(y, 5));
}
/**

@ -1,12 +1,22 @@
package de.wwwu.awolf.model.communication;
import de.wwwu.awolf.model.Line;
import de.wwwu.awolf.presenter.algorithms.Algorithm;
public class AlgorithmData implements Data {
private SubscriberType type;
private Algorithm.Type algorithmType;
private Line lineData;
public Algorithm.Type getAlgorithmType() {
return algorithmType;
}
public void setAlgorithmType(Algorithm.Type algorithmType) {
this.algorithmType = algorithmType;
}
@Override
public SubscriberType getType() {
return type;

@ -7,9 +7,7 @@ public enum SubscriberType {
EVAL_T,
LINES_RES,
LINES_RES_MULT,
LMS,
RM,
TS,
ALGORITHM,
PICTURE,
GENERATOR
}

@ -10,6 +10,7 @@ import de.wwwu.awolf.presenter.evaluation.EvaluatationHandler;
import de.wwwu.awolf.presenter.util.Logging;
import de.wwwu.awolf.view.ViewController;
import javafx.application.Platform;
import javafx.beans.property.BooleanProperty;
import java.util.Objects;
import java.util.Set;
@ -57,32 +58,20 @@ public abstract class AbstractPresenter implements Flow.Subscriber<Data> {
@Override
public void onNext(Data data) {
Logging.logDebug("Presenter received message. Type: " + data.getType());
switch (data.getType()) {
case EVALUATION_TABLE_DATA:
evaluatedDatas(data);
break;
case LMS:
visualizeLmsAlgorithm(data);
break;
case RM:
visualizeRmAlgorithm(data);
break;
case TS:
visualizeTsAlgorithm(data);
break;
case GENERATOR:
Logging.logInfo("Generierung war Erfolgreich");
case ALGORITHM:
visualizeAlgorithm(data);
break;
default:
break;
}
}
protected abstract void visualizeTsAlgorithm(Data data);
protected abstract void visualizeRmAlgorithm(Data data);
protected abstract void visualizeLmsAlgorithm(Data data);
protected abstract void visualizeAlgorithm(Data data);
protected abstract void evaluatedDatas(Data data);
@ -107,18 +96,29 @@ public abstract class AbstractPresenter implements Flow.Subscriber<Data> {
this.algorithmHandler.runAlgorithmByType(type, lines);
}
/**
* Execute an algorithm specified by a type
*
* @param type algorithm type
* @param lines set of lines
*/
public void executeAlgorithmByType(Algorithm.Type type, Set<Line> lines, BooleanProperty guiFlag) {
this.algorithmHandler.runAlgorithmByType(type, lines, guiFlag);
}
/**
* Execute an algorithm specified by a type
* (use the Lines from the LineModel)
*
* @param type algorithm type
*/
public void executeAlgorithmByType(Algorithm.Type type) {
public Line executeAlgorithmByType(Algorithm.Type type, BooleanProperty guiFlag) {
if (getModel().getSize() == 0) {
Logging.logDebug("No lines in the Model. Nothing to calculate.");
throw new IllegalArgumentException();
} else {
Logging.logDebug("AlgorithmHandler will start " + type.getName() + ", with " + getModel().getSize());
this.algorithmHandler.runAlgorithmByType(type, getModel().getLines());
return this.algorithmHandler.runAlgorithmByType(type, getModel().getLines(), guiFlag);
}
}
@ -141,7 +141,6 @@ public abstract class AbstractPresenter implements Flow.Subscriber<Data> {
*/
public void registerView(ViewController view) {
this.view = view;
Logging.enableGuiLogging();
Logging.logDebug("View has been set.");

@ -7,6 +7,7 @@ import de.wwwu.awolf.model.communication.EvaluationData;
import de.wwwu.awolf.presenter.data.DataHandler;
import de.wwwu.awolf.presenter.evaluation.EvaluatationHandler;
import de.wwwu.awolf.presenter.util.Logging;
import javafx.application.Platform;
import javax.swing.*;
import java.io.File;
@ -37,27 +38,13 @@ public class Presenter extends AbstractPresenter {
}
@Override
protected void visualizeTsAlgorithm(Data data) {
protected void visualizeAlgorithm(Data data) {
AlgorithmData algorithmData = (AlgorithmData) data;
SwingUtilities.invokeLater(() -> getView().visualizeTS(algorithmData.getLineData()));
Logging.logInfo("Theil-Sen Estimator");
Logging.logInfo(algorithmData.getLineData().toString());
}
@Override
protected void visualizeRmAlgorithm(Data data) {
AlgorithmData algorithmData = (AlgorithmData) data;
SwingUtilities.invokeLater(() -> getView().visualizeRM(algorithmData.getLineData()));
Logging.logInfo("Repeated Median Estimator");
Logging.logInfo(algorithmData.getLineData().toString());
}
@Override
protected void visualizeLmsAlgorithm(Data data) {
AlgorithmData algorithmData = (AlgorithmData) data;
SwingUtilities.invokeLater(() -> getView().visualizeLMS(algorithmData.getLineData()));
Logging.logInfo("Least Median of Squares");
Logging.logInfo(algorithmData.getLineData().toString());
Platform.runLater(() -> {
getView().getAlgorithmTabControllers().get(algorithmData.getAlgorithmType()).updatePlot(getModel(), algorithmData.getLineData());
});
Logging.logInfo("Type: " + algorithmData.getType() + ". Result: " + algorithmData.getLineData().toString());
}
@Override
@ -100,6 +87,9 @@ public class Presenter extends AbstractPresenter {
getModel().setLines(data);
//Berechnung der Schnittpunkte und vis. der Ergebnisse (anz. Geraden, anz. Schnittpunkte)
Logging.logInfo("Import was successful! ");
Platform.runLater(() -> {
getView().getAlgorithmTabControllers().values().forEach(e -> e.updatePlot(getModel(), null));
});
return data;
}
@ -113,6 +103,9 @@ public class Presenter extends AbstractPresenter {
Set<Line> data = getDataHandler().getData(type, n);
getModel().setLines(data);
Logging.logInfo("Generate was successful!");
Platform.runLater(() -> {
getView().getAlgorithmTabControllers().values().forEach(e -> e.updatePlot(getModel(), null));
});
return data;
}

@ -3,6 +3,7 @@ package de.wwwu.awolf.presenter.algorithms;
import de.wwwu.awolf.model.Line;
import de.wwwu.awolf.presenter.Presenter;
import de.wwwu.awolf.presenter.util.Logging;
import javafx.beans.property.BooleanProperty;
import javax.annotation.Nullable;
import java.util.EnumMap;
@ -38,7 +39,11 @@ public class AlgorithmHandler {
}
@Nullable
public Line runAlgorithmByType(final Algorithm.Type type, final Set<Line> setOfLines) {
public Line runAlgorithmByType(final Algorithm.Type type, final Set<Line> setOfLines, final BooleanProperty guiFlag) {
if (guiFlag != null)
guiFlag.setValue(true);
//get the instance
Algorithm algorithm = algorithmMapping.get(type);
algorithm.setPresenter(Presenter.getInstance());
@ -51,16 +56,25 @@ public class AlgorithmHandler {
completionService.submit(algorithm);
try {
return completionService.take().get();
} catch (InterruptedException e) {
Logging.logError("Interrupt Exception while waiting for result of Algorithm: " + algorithm.getType(), e);
Thread.currentThread().interrupt();
} catch (ExecutionException e) {
Logging.logError("Execution Exception while computing the result of Algorithm: " + algorithm.getType(), e);
} finally {
if (guiFlag != null)
guiFlag.setValue(false);
}
return null;
}
@Nullable
public Line runAlgorithmByType(final Algorithm.Type type, final Set<Line> setOfLines) {
return runAlgorithmByType(type, setOfLines, null);
}
private void lookUp() {
Logging.logDebug("Lookup for Algorithm Classes.");
ServiceLoader<Algorithm> load = ServiceLoader.load(Algorithm.class);

@ -362,14 +362,15 @@ public class LeastMedianOfSquaresEstimator implements Algorithm {
private Line pepareResult() {
if (this.subscriber != null) {
double m = (getSigmaMin().getX2() + getSigmaMin().getX1()) * 0.5;
double m = ((getSigmaMin().getX2() + getSigmaMin().getX1()) * 0.5);
double b = (getSigmaMin().getY2() + getSigmaMin().getY1()) * -0.5;
slope = m;
yInterception = b;
AlgorithmData data = new AlgorithmData();
data.setType(SubscriberType.LMS);
data.setAlgorithmType(getType());
data.setType(SubscriberType.ALGORITHM);
data.setLineData(new Line(m, b));
this.subscriber.onNext(data);
} else {

@ -237,7 +237,8 @@ public class RepeatedMedianEstimator implements Algorithm {
if (this.subscriber != null) {
AlgorithmData data = new AlgorithmData();
data.setType(SubscriberType.RM);
data.setAlgorithmType(getType());
data.setType(SubscriberType.ALGORITHM);
data.setLineData(new Line(getSlope(), getyInterception()));
this.subscriber.onNext(data);
}

@ -206,7 +206,8 @@ public class TheilSenEstimator implements Algorithm {
if (this.subscriber != null) {
AlgorithmData data = new AlgorithmData();
data.setType(SubscriberType.TS);
data.setAlgorithmType(getType());
data.setType(SubscriberType.ALGORITHM);
data.setLineData(new Line(m, b));
this.subscriber.onNext(data);
}

@ -1,7 +1,9 @@
package de.wwwu.awolf.presenter.algorithms.naiv;
import de.wwwu.awolf.model.Line;
import de.wwwu.awolf.model.communication.AlgorithmData;
import de.wwwu.awolf.model.communication.Data;
import de.wwwu.awolf.model.communication.SubscriberType;
import de.wwwu.awolf.presenter.AbstractPresenter;
import de.wwwu.awolf.presenter.algorithms.Algorithm;
import de.wwwu.awolf.presenter.util.FastElementSelector;
@ -66,6 +68,12 @@ public class NaivLeastMedianOfSquaresEstimator implements Algorithm {
Logging.logInfo("=== E N D - naiv L M S ===");
Logging.logInfo("Slope: " + getSlope() + ", y-Interception: " + getYInterception());
AlgorithmData data = new AlgorithmData();
data.setAlgorithmType(getType());
data.setType(SubscriberType.ALGORITHM);
data.setLineData(new Line(getSlope(), getYInterception()));
this.subscriber.onNext(data);
return new Line(getSlope(), getYInterception());
}

@ -2,7 +2,9 @@ package de.wwwu.awolf.presenter.algorithms.naiv;
import de.wwwu.awolf.model.Line;
import de.wwwu.awolf.model.Point;
import de.wwwu.awolf.model.communication.AlgorithmData;
import de.wwwu.awolf.model.communication.Data;
import de.wwwu.awolf.model.communication.SubscriberType;
import de.wwwu.awolf.presenter.AbstractPresenter;
import de.wwwu.awolf.presenter.algorithms.Algorithm;
import de.wwwu.awolf.presenter.util.FastElementSelector;
@ -85,7 +87,11 @@ public class NaivRepeatedMedianEstimator implements Algorithm {
end = System.currentTimeMillis();
Logging.logInfo("=== E N D - naiv R M ===");
Logging.logInfo("Slope: " + getSlope() + ", y-Interception: " + getYInterception());
AlgorithmData data = new AlgorithmData();
data.setAlgorithmType(getType());
data.setType(SubscriberType.ALGORITHM);
data.setLineData(new Line(getSlope(), getYInterception()));
this.subscriber.onNext(data);
return new Line(getSlope(), getYInterception());
}

@ -1,7 +1,9 @@
package de.wwwu.awolf.presenter.algorithms.naiv;
import de.wwwu.awolf.model.Line;
import de.wwwu.awolf.model.communication.AlgorithmData;
import de.wwwu.awolf.model.communication.Data;
import de.wwwu.awolf.model.communication.SubscriberType;
import de.wwwu.awolf.presenter.AbstractPresenter;
import de.wwwu.awolf.presenter.algorithms.Algorithm;
import de.wwwu.awolf.presenter.util.FastElementSelector;
@ -66,7 +68,11 @@ public class NaivTheilSenEstimator implements Algorithm {
end = System.currentTimeMillis();
Logging.logInfo("=== E N D - naiv T S ===");
Logging.logInfo("Slope: " + getSlope() + ", y-Interception: " + getYInterception());
AlgorithmData data = new AlgorithmData();
data.setAlgorithmType(getType());
data.setType(SubscriberType.ALGORITHM);
data.setLineData(new Line(getSlope(), getYInterception()));
this.subscriber.onNext(data);
return new Line(getSlope(), getYInterception());
}

@ -78,5 +78,11 @@ public class DataHandler {
CIRCLE
}
public enum ActionType {
IMPORT,
EXPORT,
GENERATE
}
}

@ -8,6 +8,7 @@ import java.util.*;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveTask;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
/**
@ -45,15 +46,21 @@ public class IntersectionComputer {
* @param higher obere Schranke
* @return Liste der Schnittpunkte
*/
public Collection<Point> compute(final List<Line> lines, final double lower, final double higher) {
public Set<Point> compute(final Collection<Line> lines, final double lower, final double higher) {
final Set<Line> fullInput = new HashSet<>(lines);
final Set<Line> copyInput = new HashSet<>(lines);
if (lower == higher) {
return Collections.emptyList();
return Collections.emptySet();
} else {
Logging.logDebug("Open ForkJoinPool: lines: " + lines.size() + " I(" + lower + ", " + higher + "]");
ForkJoinPool pool = ForkJoinPool.commonPool();
RecursiveComputationTask recursiveComputationTask = new RecursiveComputationTask(lines, lines, lower, higher);
RecursiveComputationTask recursiveComputationTask = new RecursiveComputationTask(fullInput, copyInput, lower, higher);
pool.execute(recursiveComputationTask);
return recursiveComputationTask.join();
Set<Point> join = recursiveComputationTask.join();
return join;
}
}
@ -64,7 +71,7 @@ public class IntersectionComputer {
* @param sampledLine eine spezielle Gerade
* @return Liste mit x Koordinaten der Schnittpunkte
*/
public List<Double> calculateIntersectionAbscissas(List<Line> set, Line sampledLine, double lower, double upper) {
public List<Double> calculateIntersectionAbscissas(Collection<Line> set, Line sampledLine, double lower, double upper) {
List<Line> lines = new LinkedList<>(set);
Set<Double> intersections = new HashSet<>();
@ -79,16 +86,16 @@ public class IntersectionComputer {
return new ArrayList<>(intersections);
}
private class RecursiveComputationTask extends RecursiveTask<Collection<Point>> {
private class RecursiveComputationTask extends RecursiveTask<Set<Point>> {
private static final int THRESHOLD = 20;
private static final int THRESHOLD = 200;
private final List<Line> lines;
private final List<Line> fullList;
private final Set<Line> lines;
private final Set<Line> fullList;
private final double lower;
private final double upper;
public RecursiveComputationTask(final List<Line> fullList, final List<Line> lines, final double lower, final double upper) {
public RecursiveComputationTask(final Set<Line> fullList, final Set<Line> lines, final double lower, final double upper) {
this.lines = lines;
this.fullList = fullList;
this.lower = lower;
@ -96,12 +103,11 @@ public class IntersectionComputer {
}
@Override
protected Collection<Point> compute() {
protected Set<Point> compute() {
if (this.lines.isEmpty()) {
return Collections.emptyList();
return Collections.emptySet();
} else if (this.lines.size() > THRESHOLD) {
Logging.logDebug("Bigger than threshold, split into subtask.");
return ForkJoinTask.invokeAll(createSubTask()).stream().map(ForkJoinTask::join).flatMap(Collection::stream).collect(Collectors.toList());
return ForkJoinTask.invokeAll(createSubTask()).stream().map(ForkJoinTask::join).flatMap(Collection::stream).collect(Collectors.toSet());
} else {
return work(this.fullList, this.lines, this.lower, this.upper);
}
@ -109,12 +115,27 @@ public class IntersectionComputer {
private Collection<RecursiveComputationTask> createSubTask() {
List<RecursiveComputationTask> dividedTasks = new ArrayList<>();
dividedTasks.add(new RecursiveComputationTask(this.fullList, this.lines.subList(0, this.lines.size() / 2), this.lower, this.upper));
dividedTasks.add(new RecursiveComputationTask(this.fullList, this.lines.subList(this.lines.size() / 2, this.lines.size()), this.lower, this.upper));
long midpoint = Math.round(this.lines.size() * 0.5);
Set<Line> firstSubSet = new HashSet<>();
Set<Line> secondSubSet = new HashSet<>();
AtomicInteger count = new AtomicInteger();
this.lines.forEach(next -> {
int index = count.getAndIncrement();
if (index < midpoint) {
firstSubSet.add(next);
} else {
secondSubSet.add(next);
}
});
dividedTasks.add(new RecursiveComputationTask(this.fullList, firstSubSet, this.lower, this.upper));
dividedTasks.add(new RecursiveComputationTask(this.fullList, secondSubSet, this.lower, this.upper));
return dividedTasks;
}
private Collection<Point> work(List<Line> fullList, List<Line> lines, double lower, double higher) {
private Set<Point> work(Set<Line> fullList, Set<Line> lines, double lower, double higher) {
Set<Point> points = new HashSet<>();
List<List<Line>> lists = Lists.cartesianProduct(new ArrayList<>(fullList), new ArrayList<>(lines));
lists.forEach(entry -> {

@ -10,9 +10,7 @@ public class Logging {
}
public static void enableGuiLogging() {
logger.addAppender(new GuiAppender());
}
private static Logger getLogger() {
return logger;

@ -2,23 +2,21 @@ package de.wwwu.awolf.view;
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.DataHandler;
import de.wwwu.awolf.presenter.util.Logging;
import de.wwwu.awolf.view.controller.AlgorithmTabController;
import de.wwwu.awolf.view.services.DataService;
import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXMLLoader;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.control.*;
import javafx.stage.FileChooser;
import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.*;
/**
* Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden.
@ -34,10 +32,15 @@ public class ViewController {
public TabPane tabPane;
public MenuBar menuBar;
public TextArea logArea;
private Map<Algorithm.Type, AlgorithmTabController> algorithmTabControllers;
public Map<Algorithm.Type, AlgorithmTabController> getAlgorithmTabControllers() {
return algorithmTabControllers;
}
public ViewController() {
super();
this.algorithmTabControllers = new EnumMap<>(Algorithm.Type.class);
}
public void initGui() {
@ -54,7 +57,6 @@ public class ViewController {
props.put("dsfsdfsdf", "dsadasd");
try {
for (Algorithm.Type value : Algorithm.Type.values()) {
FXMLLoader loader = new FXMLLoader();
@ -63,7 +65,9 @@ public class ViewController {
AlgorithmTabController controller = loader.getController();
controller.setAlgorithmType(value);
controller.setProperties(props);
controller.setModel(Presenter.getInstance().getModel());
controller.init();
this.algorithmTabControllers.put(value, controller);
Tab tab = new Tab(value.getName(), parent);
tab.setId(value.name());
tabPane.getTabs().add(tab);
@ -74,7 +78,6 @@ public class ViewController {
}
}
private void initMenuBar() {
@ -84,18 +87,39 @@ public class ViewController {
Menu helpMenu = new Menu("Help");
// Create MenuItems
//export the data
MenuItem exportItem = new MenuItem("Export");
exportItem.setOnAction(actionEvent -> {
FileChooser fileChooser = new FileChooser();
File file = fileChooser.showOpenDialog(null);
if (file != null && file.canWrite() && file.canRead()) {
new DataService(DataHandler.ActionType.EXPORT, file).start();
}
});
//start an import of data
MenuItem importItem = new MenuItem("Import");
importItem.setOnAction(actionEvent -> {
FileChooser fileChooser = new FileChooser();
File file = fileChooser.showOpenDialog(null);
if (file != null && file.canWrite() && file.canRead()) {
new DataService(DataHandler.ActionType.IMPORT, file).start();
}
});
//exit menu item should stop the application
MenuItem exitItem = new MenuItem("Exit");
exitItem.setOnAction(actionEvent -> {
Platform.exit();
System.exit(0);
});
// about the application
MenuItem aboutItem = new MenuItem("About");
MenuItem generationItem = new MenuItem("Generate");
generationItem.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent actionEvent) {
//TODO
new DataService(DataHandler.DataType.LINE, 100).start();
}
generationItem.setOnAction(actionEvent -> {
new DataService(DataHandler.ActionType.GENERATE, DataHandler.DataType.LINE, 1000).start();
});
MenuItem evaluationItem = new MenuItem("Evaluate");
@ -156,11 +180,6 @@ public class ViewController {
*/
public void appendEvalResult(Map<Algorithm.Type, Map<String, String>> tableEntries) {
// SwingUtilities.invokeLater(() -> {
// evaluationPanel.addRow(tableEntries);
// evaluationPanel.repaint();
// evaluationPanel.revalidate();
// });
}
/**
@ -172,154 +191,16 @@ public class ViewController {
appendEvalResult(res);
}
/*******************************************************************************************************************
* init GUI
******************************************************************************************************************/
/**
* Komponenten werden in Container gesetzt
*/
private void addComponents() {
// toolBar.add(importButton);
// toolBar.add(exportButton);
// toolBar.add(generateButton);
// toolBar.setFloatable(false);
//
// setJMenuBar(menu.getMenuBar());
// add(toolBar);
//
// setupSplitPane();
// setupTabbedPane();
// ((JPanel) progressDialog.getContentPane()).setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY));
//
// this.add(toolBar, BorderLayout.NORTH);
// this.add(splitpane, BorderLayout.CENTER);
}
/**
* Initialisierung der Komponenten
*/
private void initializeComponents(Collection<Node> list) {
// //panels
// toolBar = new JToolBar();
// lmsPanel = new LMSPanel();
// rmPanel = new RMPanel();
// tsPanel = new TSPanel();
// menu = new MenuBar();
//
// //Dialogs
// progressDialog = new JDialog();
// progressDialog.setLocationRelativeTo(null);
// progressContent = progressDialog.getContentPane();
// progressBar = new JProgressBar();
//
// //Panes
// tabbedPane = new JTabbedPane();
// output = new InfoPanel();
// splitpane = new JSplitPane();
//
// //Buttons
// importButton = new JButton();
// generateButton = new JButton();
// exportButton = new JButton();
}
/**
* Icons werden passend gesetzt
*/
private void setIcons() {
// try {
// ClassLoader classLoader = getClass().getClassLoader();
// Image imgImport = ImageIO.read(classLoader.getResource("import.png")).getScaledInstance(16, 16, Image.SCALE_SMOOTH);
// Image imgStart = ImageIO.read(classLoader.getResource("start.png")).getScaledInstance(32, 32, Image.SCALE_SMOOTH);
// Image imgGenerate = ImageIO.read(classLoader.getResource("generate.png")).getScaledInstance(16, 16, Image.SCALE_SMOOTH);
// Image imgExport = ImageIO.read(classLoader.getResource("export.png")).getScaledInstance(16, 16, Image.SCALE_SMOOTH);
// Image imgFrame = ImageIO.read(classLoader.getResource("frame.png")).getScaledInstance(32, 23, Image.SCALE_SMOOTH);
//
// importButton.setIcon(new ImageIcon(imgImport));
// exportButton.setIcon(new ImageIcon(imgExport));
// generateButton.setIcon(new ImageIcon(imgGenerate));
// lmsPanel.getStartButton().setIcon(new ImageIcon(imgStart));
// rmPanel.getStartButton().setIcon(new ImageIcon(imgStart));
// tsPanel.getStartButton().setIcon(new ImageIcon(imgStart));
// this.setIconImage(imgFrame);
// } catch (IOException e) {
// Logging.logError(e.getMessage(), e);
// }
}
/**
* Funktionalitäten werden hinzugefügt
*/
public void setActionListeners() {
// //action listener für MenuItems
// menu.addActionListeners();
//
// //action listener für diese Klasse
// lmsPanel.getStartButton().addActionListener(new StartAlgorithmListener(((Presenter) getPresenter()), lmsPanel));
// rmPanel.getStartButton().addActionListener(new StartAlgorithmListener(((Presenter) getPresenter()), rmPanel));
// tsPanel.getStartButton().addActionListener(new StartAlgorithmListener(((Presenter) getPresenter()), tsPanel));
// importButton.addActionListener(new ImportDataListener((Presenter) this.getPresenter()));
// exportButton.addActionListener(new ExportDataListener((Presenter) this.getPresenter()));
// generateButton.addActionListener(new GenerateDataListener((Presenter) this.getPresenter()));
}
/**
* Funktionalitäten werden aktiviert.
*/
public void enableFunctionality() {
// this.getLmsPanel().getStartButton().setEnabled(true);
// this.getRmPanel().getStartButton().setEnabled(true);
// this.getTsPanel().getStartButton().setEnabled(true);
// this.getExportButton().setEnabled(true);
}
/**
* Funktionalitäten werden deaktiviert.
*/
public void disableFunctionality() {
// this.getLmsPanel().getStartButton().setEnabled(false);
// this.getRmPanel().getStartButton().setEnabled(false);
// this.getTsPanel().getStartButton().setEnabled(false);
// this.getExportButton().setEnabled(false);
}
/*******************************************************************************************************************
* log Methode
******************************************************************************************************************/
/**
* @param s Text der ausgegeben wird
*/
public void logInfo(String s) {
Platform.runLater(() -> {
logArea.appendText(s + "\n");
});
}
/**
* @param s Fehlertext der ausgegeben wird
*/
public void logError(String s) {
Platform.runLater(() -> {
logArea.appendText(s + "\n");
});
}
/**
* @param s Text der in grüner Farbe ausgegeben wird
*/
public void logWarning(String s) {
Platform.runLater(() -> {
logArea.appendText(s + "\n");
});
}
/*******************************************************************************************************************
* Getter und Setter Methoden
******************************************************************************************************************/
}

@ -1,38 +1,52 @@
package de.wwwu.awolf.view.controller;
import de.wwwu.awolf.model.Line;
import de.wwwu.awolf.model.LineModel;
import de.wwwu.awolf.presenter.algorithms.Algorithm;
import de.wwwu.awolf.view.services.ButtonClickService;
import javafx.beans.property.BooleanProperty;
import javafx.fxml.FXML;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.canvas.Canvas;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.XYChart;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import java.util.Map;
public class AlgorithmTabController {
private final XYChart.Series<Double, Double> dataSerie;
private final XYChart.Series<Double, Double> lineSerie;
private Algorithm.Type algorithmType;
private Map<String, String> properties;
private LineModel model;
@FXML
public Canvas canvas;
public LineChart<Double, Double> chart;
@FXML
public VBox vBox;
@FXML
public Button startButton;
public AlgorithmTabController() {
dataSerie = new XYChart.Series<>();
dataSerie.setName("Datapoints");
lineSerie = new XYChart.Series<>();
lineSerie.setName("Estimated Line");
}
public LineModel getModel() {
return model;
}
public void setModel(LineModel model) {
this.model = model;
}
public void init() {
// add GUI elements to maintain the parameters
@ -47,7 +61,6 @@ public class AlgorithmTabController {
//label
Label label = new Label(key);
label.setAlignment(Pos.BASELINE_LEFT);
label.setFont(new Font("Arial", 17));
label.setLabelFor(textField);
label.setPadding(new Insets(2, 10, 0, 0));
@ -57,9 +70,32 @@ public class AlgorithmTabController {
vBox.getChildren().add(borderPane);
});
BooleanProperty booleanProperty = startButton.disableProperty();
startButton.setOnAction(event -> {
new ButtonClickService(algorithmType).start();
});
ButtonClickService buttonClickService = new ButtonClickService(algorithmType, booleanProperty);
buttonClickService.start();
}
);
updatePlot(this.model, null);
chart.getData().add(dataSerie);
chart.getData().add(lineSerie);
}
public void updatePlot(final LineModel model, final Line pLine) {
dataSerie.getData().clear();
model.getLines().forEach(line -> dataSerie.getData().add(new XYChart.Data<>(line.getM(), line.getB())));
if (pLine != null) {
lineSerie.getData().clear();
Double x1 = pLine.calculateX1(model.getMIN());
Double y1 = pLine.calculateY1(model.getMIN());
Double x2 = pLine.calculateX2(model.getMAX());
Double y2 = pLine.calculateY2(model.getMAX());
lineSerie.getData().add(new XYChart.Data<>(x1, y1));
lineSerie.getData().add(new XYChart.Data<>(x2, y2));
}
}
public Algorithm.Type getAlgorithmType() {
@ -77,4 +113,6 @@ public class AlgorithmTabController {
public void setProperties(Map<String, String> properties) {
this.properties = properties;
}
}

@ -1,26 +1,37 @@
package de.wwwu.awolf.view.services;
import de.wwwu.awolf.model.Line;
import de.wwwu.awolf.presenter.Presenter;
import de.wwwu.awolf.presenter.algorithms.Algorithm;
import javafx.beans.property.BooleanProperty;
import javafx.concurrent.Service;
import javafx.concurrent.Task;
public class ButtonClickService extends Service<String> {
public class ButtonClickService extends Service<Boolean> {
private final BooleanProperty startButtonDisabled;
private Algorithm.Type type;
public ButtonClickService(Algorithm.Type type) {
this.type = type;
public ButtonClickService(Algorithm.Type algorithmType, BooleanProperty startButtonDisabled) {
this.startButtonDisabled = startButtonDisabled;
this.type = algorithmType;
}
@Override
protected Task<String> createTask() {
protected Task<Boolean> createTask() {
return new Task<String>() {
return new Task<Boolean>() {
@Override
protected String call() throws Exception {
Presenter.getInstance().executeAlgorithmByType(type);
return "done";
protected Boolean call() throws Exception {
try {
Line line = Presenter.getInstance().executeAlgorithmByType(type, startButtonDisabled);
if (line != null) {
return true;
}
} catch (IllegalArgumentException e) {
return true;
}
return false;
}
};
}

@ -5,23 +5,46 @@ import de.wwwu.awolf.presenter.data.DataHandler;
import javafx.concurrent.Service;
import javafx.concurrent.Task;
public class DataService extends Service<String> {
import java.io.File;
public class DataService extends Service<Boolean> {
private File file;
private DataHandler.DataType type;
private DataHandler.ActionType actionType;
private int n;
public DataService(DataHandler.DataType type, int n) {
public DataService(final DataHandler.ActionType actionType, final DataHandler.DataType type, final int n) {
this.type = type;
this.actionType = actionType;
this.n = n;
}
public DataService(final DataHandler.ActionType actionType, final File file) {
this.actionType = actionType;
this.file = file;
this.type = null;
this.n = -1;
}
@Override
protected Task<String> createTask() {
protected Task<Boolean> createTask() {
return new Task<>() {
@Override
protected String call() throws Exception {
protected Boolean call() throws Exception {
switch (actionType) {
case EXPORT:
Presenter.getInstance().exportDataset(file);
break;
case IMPORT:
Presenter.getInstance().importDataset(file);
break;
case GENERATE:
Presenter.getInstance().generateDataset(n, type);
return "done";
break;
}
return true;
}
};
}

@ -5,7 +5,7 @@ import de.wwwu.awolf.view.ViewController;
import javafx.concurrent.Service;
import javafx.concurrent.Task;
public class GuiRegisterService extends Service<String> {
public class GuiRegisterService extends Service<Boolean> {
private final ViewController view;
@ -15,12 +15,12 @@ public class GuiRegisterService extends Service<String> {
}
@Override
protected Task<String> createTask() {
protected Task<Boolean> createTask() {
return new Task<>() {
@Override
protected String call() throws Exception {
protected Boolean call() throws Exception {
Presenter.getInstance().registerView(view);
return "Done";
return true;
}
};
}

@ -2,11 +2,11 @@
<?import javafx.geometry.*?>
<?import javafx.scene.*?>
<?import javafx.scene.canvas.*?>
<?import javafx.scene.chart.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<BorderPane prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/10.0.2-internal" xmlns:fx="http://javafx.com/fxml/1" fx:controller="de.wwwu.awolf.view.controller.AlgorithmTabController">
<BorderPane prefHeight="400.0" prefWidth="600.0" styleClass="algoPane" xmlns="http://javafx.com/javafx/10.0.2-internal" xmlns:fx="http://javafx.com/fxml/1" fx:controller="de.wwwu.awolf.view.controller.AlgorithmTabController">
<left>
<VBox fx:id="vBox" alignment="TOP_CENTER" prefHeight="200.0" prefWidth="200.0" BorderPane.alignment="CENTER">
<children>
@ -22,16 +22,6 @@
</padding>
</VBox>
</left>
<center>
<Canvas fx:id="canvas" height="334.0" width="391.0" BorderPane.alignment="CENTER" />
</center>
<bottom>
<FlowPane alignment="CENTER" minWidth="-Infinity">
<BorderPane.margin>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
</BorderPane.margin>
</FlowPane>
</bottom>
<top>
<FlowPane hgap="5.0" prefHeight="25.0" prefWidth="200.0" BorderPane.alignment="CENTER">
<children>
@ -46,4 +36,20 @@
</BorderPane.margin>
</FlowPane>
</top>
<center>
<LineChart fx:id="chart" prefHeight="398.0" prefWidth="390.0" title="Plot" BorderPane.alignment="CENTER">
<xAxis>
<NumberAxis label="X" side="BOTTOM">
<padding>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
</padding></NumberAxis>
</xAxis>
<yAxis>
<NumberAxis label="Y" side="LEFT">
<padding>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
</padding></NumberAxis>
</yAxis>
</LineChart>
</center>
</BorderPane>

@ -12,12 +12,6 @@
<center>
<TabPane fx:id="tabPane" prefHeight="200.0" prefWidth="200.0" tabClosingPolicy="UNAVAILABLE" BorderPane.alignment="CENTER">
<tabs>
<Tab text="Logging">
<BorderPane xmlns="http://javafx.com/javafx/10.0.2-internal" xmlns:fx="http://javafx.com/fxml/1">
<center>
<TextArea fx:id="logArea" editable="false" prefHeight="200.0" prefWidth="200.0" BorderPane.alignment="CENTER" />
</center></BorderPane>
</Tab>
</tabs>
</TabPane>
</center>

@ -1,5 +1,18 @@
package de.wwwu.awolf.presenter.algorithms.advanced;
import de.wwwu.awolf.model.Line;
import de.wwwu.awolf.presenter.algorithms.Algorithm;
import de.wwwu.awolf.presenter.algorithms.AlgorithmHandler;
import org.junit.Before;
import org.junit.Test;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
/**
* Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden.
*
@ -9,68 +22,44 @@ package de.wwwu.awolf.presenter.algorithms.advanced;
*/
public class LeastMedianOfSquaresEstimatorTest {
// private LeastMedianOfSquaresEstimator lms;
//
// @Before
// public void setUp(){
// Double[] x = {18d, 24d, 30d, 34d, 38d};
// Double[] y = {18d, 26d, 30d, 40d, 70d};
//
//
// LinkedList<Line> lines = new LinkedList<>();
//
// for (int i = 0; i < 5; i++) {
// lines.add(new Line(x[i], y[i]));
// }
//
// lms = new LeastMedianOfSquaresEstimator(lines);
// }
//
//
// @Test
// public void geEjValues() throws Exception {
//
// Double[] expected = {36d, 50d, 60d, 74d, 108d};
// List<Double> actual = lms.getEjValues(1d);
// assertArrayEquals(expected, actual.toArray());
// }
//
// @Test
// public void calcKMinusBracelet() throws Exception {
//
// Point point = new Point(1d, 1d);
// Double[] expected = {24d, 36d, 60d};
// Double[] actual = lms.calcKMinusBracelet(point, 3);
//
// assertArrayEquals(expected, actual);
//
// }
//
// @Test
// public void upperBound() throws Exception {
// lms.setkMinus(3);
// lms.setHeightsigmaMin(500);
// lms.setSigmaMin(new Line(0, 0, 0, 0));
// lms.setN(5);
// Line expected = new Line(5, 5, 146, 210);
// lms.upperBound(5d);
//
// assertEquals(expected.getX1(), lms.getSigmaMin().getX1(), 0.01);
// assertEquals(expected.getX2(), lms.getSigmaMin().getX2(), 0.01);
// assertEquals(expected.getY1(), lms.getSigmaMin().getY1(), 0.01);
// assertEquals(expected.getY2(), lms.getSigmaMin().getY2(), 0.01);
// }
//
// @Test
// public void lowerBound() throws Exception {
// //kann nur über sout geprüft werden test passt aber
// Double[] expectedAlpha = {0d, 0d, 0d, 2d, 4d};
// Double[] expectedBeta = {2d, 4d, 4d, 2d, 1d};
// lms.setHeightsigmaMin(500);
//
// Interval interval = new Interval(-2, 0);
// lms.lowerBound(interval);
// assertTrue(interval.getActivity());
// }
private LeastMedianOfSquaresEstimator lms;
private Set<Line> lines;
private Line line;
@Before
public void setUp(){
Double[] x = {18d, 24d, 30d, 34d, 38d};
Double[] y = {18d, 26d, 30d, 40d, 70d};
lines = new HashSet<>();
for (int i = 0; i < 5; i++) {
lines.add(new Line(x[i], y[i]));
}
line = AlgorithmHandler.getInstance().runAlgorithmByType(Algorithm.Type.LMS, lines);
}
@Test
public void geEjValues() throws Exception {
Double[] expected = {36d, 50d, 60d, 74d, 108d};
List<Double> actual = lms.getEjValues(1d);
assertArrayEquals(expected, actual.toArray());
}
@Test
public void upperBound() throws Exception {
Line expected = new Line(5, 5, 146, 210);
assertEquals(expected.getX1(), line.getX1(), 0.01);
assertEquals(expected.getX2(), line.getX2(), 0.01);
assertEquals(expected.getY1(), line.getY1(), 0.01);
assertEquals(expected.getY2(), line.getY2(), 0.01);
}
}

@ -1,5 +1,11 @@
package de.wwwu.awolf.presenter.algorithms.advanced;
import de.wwwu.awolf.model.Line;
import org.junit.Before;
import java.util.LinkedList;
import java.util.List;
/**
* Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden.
*
@ -8,47 +14,20 @@ package de.wwwu.awolf.presenter.algorithms.advanced;
* @Date: 23.10.2017.
*/
public class TheilSenEstimatorTest {
//
// TheilSenEstimator estimator;
//
// @Before
// public void setUp(){
// Double[] x = {18d, 24d, 30d, 34d, 38d};
// Double[] y = {18d, 26d, 30d, 40d, 70d};
//
//
// List<Line> lines = new LinkedList<>();
//
// for (int i = 0; i < 5; i++) {
// lines.add(new Line(x[i], y[i]));
// }
//
// estimator = new TheilSenEstimator(lines);
// }
//
//
// @Test
// public void getIntervalSize() throws Exception {
// // assertEquals(estimator.getIntervalSize(-2d, 0d), 5, 0.001);
// }
//
// @Test
// public void getOpenIntervalSize() throws Exception {
// // assertEquals(estimator.getIntervalSize(-1.4d, 0.6666d), 4, 0.001);
// }
//
// @Test
// public void getOpenIntervalElements() throws Exception {
// List<Point> intersectionInInterval = estimator.getOpenIntervalElements(-1.4d, -0.67d);
// double[] expected = {-1.375, -1.333, -1.0};
// double[] actual = new double[3];
// for (int i=0;i<intersectionInInterval.size();i++) {
// actual[i] = intersectionInInterval.get(i).getX();
// }
//
// Arrays.sort(expected);
// Arrays.sort(actual);
// assertArrayEquals(expected, actual, 0.001);
// }
@Before
public void setUp(){
Double[] x = {18d, 24d, 30d, 34d, 38d};
Double[] y = {18d, 26d, 30d, 40d, 70d};
List<Line> lines = new LinkedList<>();
for (int i = 0; i < 5; i++) {
lines.add(new Line(x[i], y[i]));
}
}
}

@ -5,6 +5,10 @@ import de.wwwu.awolf.model.LineModel;
import org.junit.Before;
import org.junit.Test;
import java.util.ArrayList;
import static org.junit.Assert.assertEquals;
/**
* Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden.
*
@ -29,8 +33,8 @@ public class IntersectionCounterTest {
@Test
public void run() throws Exception {
// IntersectionComputer instance = IntersectionComputer.getInstance();
// assertEquals(3, IntersectionComputer.getInstance().compute(lineModel.getLines(), -9999,9999).size());
IntersectionComputer instance = IntersectionComputer.getInstance();
assertEquals(3, IntersectionComputer.getInstance().compute(new ArrayList<>(lineModel.getLines()), -9999,9999).size());
}
}

Binary file not shown.

Binary file not shown.
Loading…
Cancel
Save