2020-03-21 00:37:09 +00:00
|
|
|
|
package de.wwwu.awolf.presenter.algorithms.advanced;
|
|
|
|
|
|
|
|
|
|
import de.wwwu.awolf.model.Interval;
|
|
|
|
|
import de.wwwu.awolf.model.Line;
|
2020-03-23 06:58:40 +00:00
|
|
|
|
import de.wwwu.awolf.model.Point;
|
2020-03-21 00:37:09 +00:00
|
|
|
|
import de.wwwu.awolf.model.communication.AlgorithmData;
|
|
|
|
|
import de.wwwu.awolf.model.communication.Data;
|
|
|
|
|
import de.wwwu.awolf.model.communication.SubscriberType;
|
2020-03-28 15:24:35 +00:00
|
|
|
|
import de.wwwu.awolf.presenter.AbstractPresenter;
|
2020-03-21 00:37:09 +00:00
|
|
|
|
import de.wwwu.awolf.presenter.algorithms.Algorithm;
|
2020-03-28 15:24:35 +00:00
|
|
|
|
import de.wwwu.awolf.presenter.util.FastElementSelector;
|
|
|
|
|
import de.wwwu.awolf.presenter.util.IntersectionComputer;
|
|
|
|
|
import de.wwwu.awolf.presenter.util.Logging;
|
|
|
|
|
import de.wwwu.awolf.presenter.util.RandomSampler;
|
2020-04-05 18:53:52 +00:00
|
|
|
|
import java.util.ArrayList;
|
|
|
|
|
import java.util.Collections;
|
|
|
|
|
import java.util.HashSet;
|
|
|
|
|
import java.util.LinkedList;
|
|
|
|
|
import java.util.List;
|
|
|
|
|
import java.util.Set;
|
2020-03-21 00:37:09 +00:00
|
|
|
|
import java.util.concurrent.Flow;
|
2017-09-10 15:45:47 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden.
|
|
|
|
|
*
|
|
|
|
|
* @Author: Armin Wolf
|
|
|
|
|
* @Email: a_wolf28@uni-muenster.de
|
|
|
|
|
* @Date: 28.05.2017.
|
|
|
|
|
*/
|
2020-03-28 15:24:35 +00:00
|
|
|
|
public class RepeatedMedianEstimator implements Algorithm {
|
2017-09-10 15:45:47 +00:00
|
|
|
|
|
2020-03-28 15:24:35 +00:00
|
|
|
|
|
|
|
|
|
private static final Algorithm.Type type = Type.RM;
|
|
|
|
|
|
|
|
|
|
private AbstractPresenter presenter;
|
2020-03-23 06:58:40 +00:00
|
|
|
|
private List<Line> setOfLines;
|
2017-09-10 15:45:47 +00:00
|
|
|
|
private Interval interval;
|
2020-03-23 06:58:40 +00:00
|
|
|
|
private Interval original;
|
2017-09-10 15:45:47 +00:00
|
|
|
|
|
|
|
|
|
//in der Literatur als L_i, C_i, und R_i bekannt
|
2020-03-23 06:58:40 +00:00
|
|
|
|
private int countLeftSlab;
|
|
|
|
|
private int countCenterSlab;
|
|
|
|
|
private int countRightSlab;
|
2017-09-10 15:45:47 +00:00
|
|
|
|
|
2020-03-23 06:58:40 +00:00
|
|
|
|
//in der Literatur als L_i, C_i, und R_i bekannt
|
|
|
|
|
private Set<Point> intersectionsInLeftSlab;
|
|
|
|
|
private Set<Point> intersectionsInCenterSlab;
|
|
|
|
|
private Set<Point> intersectionsInRightSlab;
|
2017-09-10 15:45:47 +00:00
|
|
|
|
|
2019-08-01 05:19:04 +00:00
|
|
|
|
private double r;
|
|
|
|
|
private int n;
|
|
|
|
|
private double k;
|
|
|
|
|
private double kLow;
|
|
|
|
|
private double kHigh;
|
|
|
|
|
private double beta;
|
2017-09-10 15:45:47 +00:00
|
|
|
|
|
2019-08-01 05:19:04 +00:00
|
|
|
|
private double slope;
|
|
|
|
|
private double yInterception;
|
2020-03-21 00:37:09 +00:00
|
|
|
|
private Flow.Subscriber<? super AlgorithmData> subscriber;
|
2017-09-10 15:45:47 +00:00
|
|
|
|
|
2020-03-28 15:24:35 +00:00
|
|
|
|
|
2017-10-15 13:21:53 +00:00
|
|
|
|
/**
|
2020-03-28 15:24:35 +00:00
|
|
|
|
* Führt den Algortihmus zur Berechnung des RM-Schätzers durch.
|
|
|
|
|
* <p>
|
2020-04-05 18:53:52 +00:00
|
|
|
|
* Paper: Matousek, Jiri, D. M. Mount und N. S. Netanyahu „Efficient Randomized Algorithms for the Repeated Median Line Estimator“. 1998 Algorithmica 20.2, S. 136–150
|
2017-10-15 13:21:53 +00:00
|
|
|
|
*/
|
2020-03-28 15:24:35 +00:00
|
|
|
|
public Line call() {
|
|
|
|
|
|
2020-03-23 06:58:40 +00:00
|
|
|
|
n = setOfLines.size();
|
2020-03-28 15:24:35 +00:00
|
|
|
|
interval = new Interval(-10000, 10000);
|
|
|
|
|
original = new Interval(-10000, 10000);
|
2017-09-10 15:45:47 +00:00
|
|
|
|
beta = 0.5;
|
2020-03-23 06:58:40 +00:00
|
|
|
|
|
|
|
|
|
intersectionsInLeftSlab = new HashSet<>();
|
|
|
|
|
intersectionsInCenterSlab = new HashSet<>();
|
|
|
|
|
intersectionsInRightSlab = new HashSet<>();
|
|
|
|
|
|
2020-03-28 15:24:35 +00:00
|
|
|
|
intersectionsInLeftSlab.add(new Point(0d, 0d));
|
|
|
|
|
intersectionsInCenterSlab.add(new Point(0d, 0d));
|
|
|
|
|
intersectionsInCenterSlab.add(new Point(0d, 0d));
|
2017-09-10 15:45:47 +00:00
|
|
|
|
|
|
|
|
|
for (int i = 0; i < n; i++) {
|
2020-03-23 06:58:40 +00:00
|
|
|
|
countLeftSlab = 0;
|
|
|
|
|
countRightSlab = 0;
|
|
|
|
|
countCenterSlab = setOfLines.size();
|
2017-09-10 15:45:47 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-03-21 00:37:09 +00:00
|
|
|
|
Logging.logInfo("=== S T A R T - R M ===");
|
2017-10-12 15:21:16 +00:00
|
|
|
|
long start;
|
|
|
|
|
long end;
|
|
|
|
|
start = System.currentTimeMillis();
|
2020-03-23 06:58:40 +00:00
|
|
|
|
double thetaLow = 0;
|
|
|
|
|
double thetaHigh = 0;
|
2017-10-12 15:21:16 +00:00
|
|
|
|
|
2020-03-23 06:58:40 +00:00
|
|
|
|
while (countCenterSlab > 1) {
|
|
|
|
|
n = countCenterSlab;
|
2017-09-10 15:45:47 +00:00
|
|
|
|
r = Math.ceil(Math.pow(n, beta));
|
2020-03-23 06:58:40 +00:00
|
|
|
|
List<Line> lines = RandomSampler.run(setOfLines, r);
|
2017-09-10 15:45:47 +00:00
|
|
|
|
|
2017-10-15 13:21:53 +00:00
|
|
|
|
//Für jede Gerade aus der Stichprobe wird der Schnittpunkt mit der medianen
|
|
|
|
|
//x-Koordinate bestimmt
|
2020-03-21 00:37:09 +00:00
|
|
|
|
List<Double> medianIntersectionAbscissas = new ArrayList<>();
|
2020-03-23 06:58:40 +00:00
|
|
|
|
final double lowerBound = thetaLow;
|
|
|
|
|
final double upperBound = thetaHigh;
|
|
|
|
|
if (!lines.isEmpty()) {
|
2020-04-05 18:53:52 +00:00
|
|
|
|
lines.forEach(line -> medianIntersectionAbscissas
|
|
|
|
|
.add(estimateMedianIntersectionAbscissas(lines, line)));
|
2017-09-10 15:45:47 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-10-15 13:21:53 +00:00
|
|
|
|
//Rang vom RM-Wert in C
|
2020-03-23 06:58:40 +00:00
|
|
|
|
k = Math.max(1, Math.min(n, (Math.ceil(n * 0.5) - countLeftSlab)));
|
2017-09-10 15:45:47 +00:00
|
|
|
|
|
2017-10-15 13:21:53 +00:00
|
|
|
|
//berechne k_lo und k_hi
|
2017-09-10 15:45:47 +00:00
|
|
|
|
computeSlabBorders();
|
|
|
|
|
|
2017-10-15 13:21:53 +00:00
|
|
|
|
//Berechne die Elemente mit dem Rang Theta_lo und Theta_hi
|
2020-03-23 06:58:40 +00:00
|
|
|
|
Collections.sort(medianIntersectionAbscissas);
|
2020-04-05 18:53:52 +00:00
|
|
|
|
thetaLow = FastElementSelector
|
|
|
|
|
.randomizedSelect(medianIntersectionAbscissas, kLow);
|
|
|
|
|
thetaHigh = FastElementSelector
|
|
|
|
|
.randomizedSelect(medianIntersectionAbscissas, kHigh);
|
2017-09-10 15:45:47 +00:00
|
|
|
|
|
2017-10-15 13:21:53 +00:00
|
|
|
|
//Für jede Gerade in C wird die Anzahl der Schnittpunkte die im Intervall liegen hochgezählt
|
2020-03-23 06:58:40 +00:00
|
|
|
|
countNumberOfIntersectionsAbscissas(thetaLow, thetaHigh);
|
2017-09-10 15:45:47 +00:00
|
|
|
|
|
2017-10-15 13:21:53 +00:00
|
|
|
|
//verkleinere das Intervall
|
2020-03-23 06:58:40 +00:00
|
|
|
|
contractIntervals(thetaLow, thetaHigh);
|
2017-09-10 15:45:47 +00:00
|
|
|
|
|
|
|
|
|
}
|
2020-03-23 06:58:40 +00:00
|
|
|
|
|
2017-10-12 15:21:16 +00:00
|
|
|
|
end = System.currentTimeMillis();
|
2020-03-23 06:58:40 +00:00
|
|
|
|
Logging.logInfo("=== E N D - R M === " + ((end - start) / 1000));
|
2019-08-01 05:19:04 +00:00
|
|
|
|
|
2020-03-23 06:58:40 +00:00
|
|
|
|
return pepareResult(thetaLow, thetaHigh);
|
2017-09-10 15:45:47 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-03-28 15:24:35 +00:00
|
|
|
|
@Override
|
|
|
|
|
public void setInput(Set<Line> lines) {
|
|
|
|
|
this.setOfLines = new LinkedList<>(lines);
|
|
|
|
|
this.n = setOfLines.size();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public Type getType() {
|
|
|
|
|
return type;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void setPresenter(AbstractPresenter presenter) {
|
|
|
|
|
this.presenter = presenter;
|
|
|
|
|
subscribe(presenter);
|
|
|
|
|
}
|
|
|
|
|
|
2017-09-10 15:45:47 +00:00
|
|
|
|
|
|
|
|
|
/**
|
2017-10-15 13:21:53 +00:00
|
|
|
|
* Berechnet die mediane x-Koordinate über den Schnittpunkten.
|
|
|
|
|
*
|
|
|
|
|
* @param sampledLine Stichprobe von Geraden
|
2020-03-20 17:08:18 +00:00
|
|
|
|
* @return mediane x-Koordinate über den Schnittpunkten
|
2017-09-10 15:45:47 +00:00
|
|
|
|
*/
|
2020-03-23 06:58:40 +00:00
|
|
|
|
public Double estimateMedianIntersectionAbscissas(List<Line> lines, Line sampledLine) {
|
2017-09-10 15:45:47 +00:00
|
|
|
|
|
2020-04-05 18:53:52 +00:00
|
|
|
|
List<Double> intersections = IntersectionComputer.getInstance()
|
|
|
|
|
.calculateIntersectionAbscissas(lines, sampledLine, original.getLower(),
|
|
|
|
|
original.getUpper());
|
|
|
|
|
List<Double> left = IntersectionComputer.getInstance()
|
|
|
|
|
.calculateIntersectionAbscissas(lines, sampledLine, original.getLower(),
|
|
|
|
|
interval.getLower());
|
|
|
|
|
List<Double> center = IntersectionComputer.getInstance()
|
|
|
|
|
.calculateIntersectionAbscissas(lines, sampledLine, interval.getLower(),
|
|
|
|
|
interval.getUpper());
|
2017-09-10 15:45:47 +00:00
|
|
|
|
|
2020-03-23 06:58:40 +00:00
|
|
|
|
double ki = Math.ceil((n - 1) * 0.5) - left.size();
|
|
|
|
|
double i = (Math.ceil((Math.sqrt(n) * ki) / center.size()));
|
2017-09-10 15:45:47 +00:00
|
|
|
|
int accessIndex;
|
2020-04-05 18:53:52 +00:00
|
|
|
|
if (i < 0) {
|
2017-09-10 15:45:47 +00:00
|
|
|
|
accessIndex = 0;
|
2020-04-05 18:53:52 +00:00
|
|
|
|
} else if (i >= intersections.size() && !intersections.isEmpty()) {
|
2017-09-10 15:45:47 +00:00
|
|
|
|
accessIndex = intersections.size() - 1;
|
2020-04-05 18:53:52 +00:00
|
|
|
|
} else {
|
2017-09-10 15:45:47 +00:00
|
|
|
|
accessIndex = (int) i;
|
2020-04-05 18:53:52 +00:00
|
|
|
|
}
|
2017-09-10 15:45:47 +00:00
|
|
|
|
|
|
|
|
|
return FastElementSelector.randomizedSelect(intersections, accessIndex);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2017-10-15 13:21:53 +00:00
|
|
|
|
* Berechnet die potenziell neuen Intervallgrenzen.
|
2017-09-10 15:45:47 +00:00
|
|
|
|
*/
|
|
|
|
|
public void computeSlabBorders() {
|
2020-03-23 06:58:40 +00:00
|
|
|
|
kLow = Math.max(1, Math.floor(((r * k) / (countCenterSlab))
|
2020-04-05 18:53:52 +00:00
|
|
|
|
- ((3 * Math.sqrt(r)) * (0.5))));
|
2020-03-23 06:58:40 +00:00
|
|
|
|
kHigh = Math.min(r, Math.floor(((r * k) / (countCenterSlab))
|
2020-04-05 18:53:52 +00:00
|
|
|
|
+ ((3 * Math.sqrt(r)) * (0.5))));
|
2017-09-10 15:45:47 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2020-04-05 18:53:52 +00:00
|
|
|
|
* Berechnet die Anzahl der Schnittpunkte pro Bereich. Insgesammt gibt es drei Bereiche: Im Intervall => (a,b], vor dem Intervall => (a', a], hinter dem Intervall => (b, b'].
|
2017-09-10 15:45:47 +00:00
|
|
|
|
*/
|
2020-03-28 15:24:35 +00:00
|
|
|
|
public void countNumberOfIntersectionsAbscissas(final double lower, final double upper) {
|
2020-03-23 06:58:40 +00:00
|
|
|
|
IntersectionComputer instance = IntersectionComputer.getInstance();
|
2017-09-10 15:45:47 +00:00
|
|
|
|
|
2020-04-05 18:53:52 +00:00
|
|
|
|
intersectionsInLeftSlab = new HashSet<>(
|
|
|
|
|
instance.compute(setOfLines, interval.getLower(), lower));
|
2020-03-23 06:58:40 +00:00
|
|
|
|
intersectionsInCenterSlab = new HashSet<>(instance.compute(setOfLines, lower, upper));
|
2020-04-05 18:53:52 +00:00
|
|
|
|
intersectionsInRightSlab = new HashSet<>(
|
|
|
|
|
instance.compute(setOfLines, upper, interval.getUpper()));
|
2020-03-23 06:58:40 +00:00
|
|
|
|
|
2020-04-05 18:53:52 +00:00
|
|
|
|
int tmp = new HashSet<>(
|
|
|
|
|
instance.compute(setOfLines, interval.getLower(), interval.getUpper()))
|
|
|
|
|
.size();
|
2020-03-23 06:58:40 +00:00
|
|
|
|
countLeftSlab = intersectionsInLeftSlab.size();
|
|
|
|
|
countCenterSlab = intersectionsInCenterSlab.size();
|
|
|
|
|
countRightSlab = intersectionsInRightSlab.size();
|
2017-09-10 15:45:47 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2020-04-05 18:53:52 +00:00
|
|
|
|
* Verkleinert das aktuelle Intervall. Eines der drei Bereiche wird als neues Intervall gewählt. Auf diesem Intervall werden dann in der nächsten Iteration wieder drei Bereiche bestimmt.
|
2017-09-10 15:45:47 +00:00
|
|
|
|
*/
|
2020-03-28 15:24:35 +00:00
|
|
|
|
public void contractIntervals(final double lower, final double upper) {
|
2020-03-23 06:58:40 +00:00
|
|
|
|
double max = Math.max(countLeftSlab, Math.max(countCenterSlab, countRightSlab));
|
2017-09-10 15:45:47 +00:00
|
|
|
|
|
2020-04-05 18:53:52 +00:00
|
|
|
|
boolean newIntervalIsC =
|
|
|
|
|
countLeftSlab < Math.ceil(n * 0.5)
|
|
|
|
|
&& Math.ceil(n * 0.5) <= countLeftSlab + countCenterSlab;
|
2020-03-23 06:58:40 +00:00
|
|
|
|
boolean newIntervalIsL = Math.ceil(n * 0.5) <= countLeftSlab;
|
2020-04-05 18:53:52 +00:00
|
|
|
|
boolean newIntervalIsR =
|
|
|
|
|
countLeftSlab + countCenterSlab < Math.ceil(n * 0.5) && Math.ceil(n * 0.5) <= (
|
|
|
|
|
countLeftSlab
|
|
|
|
|
+ countCenterSlab + countRightSlab);
|
2017-09-10 15:45:47 +00:00
|
|
|
|
|
|
|
|
|
//wähle C als C
|
2020-03-23 06:58:40 +00:00
|
|
|
|
if (newIntervalIsC) {
|
|
|
|
|
interval.setLower(lower);
|
|
|
|
|
interval.setUpper(upper);
|
|
|
|
|
} else if (newIntervalIsL) {
|
|
|
|
|
interval.setUpper(lower);
|
|
|
|
|
} else if (newIntervalIsR) {
|
|
|
|
|
interval.setLower(upper);
|
2017-09-10 15:45:47 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-23 06:58:40 +00:00
|
|
|
|
private Line pepareResult(final double thetaLow, final double thetaHigh) {
|
|
|
|
|
slope = thetaLow;
|
2020-03-28 15:24:35 +00:00
|
|
|
|
List<Double> potentialYInterceptions = new ArrayList<>();
|
2020-03-23 06:58:40 +00:00
|
|
|
|
setOfLines.forEach(line -> {
|
|
|
|
|
potentialYInterceptions.add(line.getB() - (slope * line.getM()));
|
|
|
|
|
});
|
2017-09-10 15:45:47 +00:00
|
|
|
|
|
2020-04-05 18:53:52 +00:00
|
|
|
|
yInterception = FastElementSelector.randomizedSelect(potentialYInterceptions,
|
|
|
|
|
Math.floor(potentialYInterceptions.size() * 0.5));
|
2020-03-23 06:58:40 +00:00
|
|
|
|
|
|
|
|
|
if (this.subscriber != null) {
|
2020-03-21 00:37:09 +00:00
|
|
|
|
AlgorithmData data = new AlgorithmData();
|
2020-04-05 17:28:38 +00:00
|
|
|
|
data.setAlgorithmType(getType());
|
|
|
|
|
data.setType(SubscriberType.ALGORITHM);
|
2020-03-23 06:58:40 +00:00
|
|
|
|
data.setLineData(new Line(getSlope(), getyInterception()));
|
2020-03-21 00:37:09 +00:00
|
|
|
|
this.subscriber.onNext(data);
|
2017-09-10 15:45:47 +00:00
|
|
|
|
}
|
2020-03-21 19:54:03 +00:00
|
|
|
|
|
|
|
|
|
return new Line(getSlope(), getyInterception());
|
2017-09-10 15:45:47 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-10-15 13:21:53 +00:00
|
|
|
|
/**
|
|
|
|
|
* @return Anzahl der Geraden
|
|
|
|
|
*/
|
2017-09-10 15:45:47 +00:00
|
|
|
|
public Integer getN() {
|
|
|
|
|
return n;
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-15 13:21:53 +00:00
|
|
|
|
/**
|
|
|
|
|
* @param n Anzahl der Geraden
|
|
|
|
|
*/
|
2017-09-10 15:45:47 +00:00
|
|
|
|
public void setN(Integer n) {
|
|
|
|
|
this.n = n;
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-15 13:21:53 +00:00
|
|
|
|
/**
|
|
|
|
|
* @param beta Parameter Beta
|
|
|
|
|
*/
|
2017-09-10 15:45:47 +00:00
|
|
|
|
public void setBeta(Double beta) {
|
|
|
|
|
this.beta = beta;
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-15 13:21:53 +00:00
|
|
|
|
/**
|
|
|
|
|
* @return Steigung
|
|
|
|
|
*/
|
2017-09-10 15:45:47 +00:00
|
|
|
|
public Double getSlope() {
|
|
|
|
|
return slope;
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-15 13:21:53 +00:00
|
|
|
|
/**
|
|
|
|
|
* @return y-Achsenabschnitt
|
|
|
|
|
*/
|
2017-09-10 15:45:47 +00:00
|
|
|
|
public Double getyInterception() {
|
|
|
|
|
return yInterception;
|
|
|
|
|
}
|
2017-10-23 15:48:36 +00:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @return temporäres untere Intervallgrenze
|
|
|
|
|
*/
|
|
|
|
|
public Double getkLow() {
|
|
|
|
|
return kLow;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @param kLow temporäres untere Intervallgrenze
|
|
|
|
|
*/
|
|
|
|
|
public void setkLow(Double kLow) {
|
|
|
|
|
this.kLow = kLow;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @return temporäres oberes Intervallgrenze
|
|
|
|
|
*/
|
|
|
|
|
public Double getkHigh() {
|
|
|
|
|
return kHigh;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @param kHigh temporäres oberes Intervallgrenze
|
|
|
|
|
*/
|
|
|
|
|
public void setkHigh(Double kHigh) {
|
|
|
|
|
this.kHigh = kHigh;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2020-03-20 17:08:18 +00:00
|
|
|
|
* @return verteilung der Punkte
|
2017-10-23 15:48:36 +00:00
|
|
|
|
*/
|
2020-03-23 06:58:40 +00:00
|
|
|
|
public int getCountLeftSlab() {
|
2017-10-23 15:48:36 +00:00
|
|
|
|
return countLeftSlab;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @return verteilung der Punkte
|
|
|
|
|
*/
|
2020-03-23 06:58:40 +00:00
|
|
|
|
public int getCountCenterSlab() {
|
2017-10-23 15:48:36 +00:00
|
|
|
|
return countCenterSlab;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @return verteilung der Punkte
|
|
|
|
|
*/
|
2020-03-23 06:58:40 +00:00
|
|
|
|
public int getCountRightSlab() {
|
2017-10-23 15:48:36 +00:00
|
|
|
|
return countRightSlab;
|
|
|
|
|
}
|
2020-03-21 00:37:09 +00:00
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void subscribe(Flow.Subscriber<? super Data> subscriber) {
|
|
|
|
|
this.subscriber = subscriber;
|
|
|
|
|
}
|
2017-09-10 15:45:47 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|