junit hinzugefügt
This commit is contained in:
parent
a585f903e6
commit
b428dee264
|
@ -9,7 +9,7 @@ import presenter.algorithms.advanced.TheilSenEstimator;
|
|||
import presenter.algorithms.naiv.NaivLeastMedianOfSquaresEstimator;
|
||||
import presenter.algorithms.naiv.NaivRepeatedMedianEstimator;
|
||||
import presenter.algorithms.naiv.NaivTheilSenEstimator;
|
||||
import presenter.algorithms.util.IntersectionComputer;
|
||||
import presenter.util.IntersectionComputer;
|
||||
import presenter.generator.DatasetGenerator;
|
||||
import view.MainFrame;
|
||||
|
||||
|
@ -18,8 +18,6 @@ import java.awt.*;
|
|||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
|
||||
import static nu.pattern.OpenCV.loadShared;
|
||||
|
||||
/**
|
||||
* Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden.
|
||||
*
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package presenter;
|
||||
|
||||
import model.LineModel;
|
||||
import presenter.algorithms.util.IntersectionComputer;
|
||||
import presenter.util.IntersectionComputer;
|
||||
import presenter.evaluation.EvaluateAlgorithms;
|
||||
import view.MainFrame;
|
||||
|
||||
|
@ -138,7 +138,13 @@ public abstract class AbstractPresenter implements Observer {
|
|||
*/
|
||||
protected void computeIntersections(){
|
||||
Thread t = new Thread(() -> {
|
||||
long start, end;
|
||||
|
||||
start = System.currentTimeMillis();
|
||||
startIntersectionCalculation();
|
||||
end = System.currentTimeMillis();
|
||||
|
||||
System.out.println("Zeit: "+(end-start)/1000);
|
||||
});
|
||||
t.start();
|
||||
try {
|
||||
|
|
|
@ -5,7 +5,7 @@ import model.Line;
|
|||
import model.Point;
|
||||
import presenter.Presenter;
|
||||
import presenter.algorithms.Algorithm;
|
||||
import presenter.algorithms.util.IntersectionCounter;
|
||||
import presenter.util.IntersectionCounter;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
|
|
|
@ -4,15 +4,14 @@ import model.Interval;
|
|||
import model.Line;
|
||||
import presenter.Presenter;
|
||||
import presenter.algorithms.Algorithm;
|
||||
import presenter.algorithms.util.FastElementSelector;
|
||||
import presenter.algorithms.util.IntersectionCounter;
|
||||
import presenter.algorithms.util.RandomSampler;
|
||||
import presenter.util.FastElementSelector;
|
||||
import presenter.util.IntersectionCounter;
|
||||
import presenter.util.RandomSampler;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Observable;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -301,6 +300,55 @@ public class RepeatedMedianEstimator extends Observable implements Algorithm {
|
|||
public Double getyInterception() {
|
||||
return yInterception;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return verteilung der Punkte
|
||||
*/
|
||||
public ArrayList<Double> getCountLeftSlab() {
|
||||
return countLeftSlab;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return verteilung der Punkte
|
||||
*/
|
||||
public ArrayList<Double> getCountCenterSlab() {
|
||||
return countCenterSlab;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return verteilung der Punkte
|
||||
*/
|
||||
public ArrayList<Double> getCountRightSlab() {
|
||||
return countRightSlab;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ import model.Line;
|
|||
import model.Point;
|
||||
import presenter.Presenter;
|
||||
import presenter.algorithms.Algorithm;
|
||||
import presenter.algorithms.util.*;
|
||||
import presenter.util.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
|
@ -63,6 +63,8 @@ public class TheilSenEstimator extends Observable implements Algorithm {
|
|||
this.N = BinomialCoeffizient.run(n, 2);
|
||||
//this.k = Integer.valueOf((int) (N * 0.5)) - 1;
|
||||
this.k = (int) (N / 2);
|
||||
|
||||
interval = new Interval(NEGATIV_INF, POSITIV_INF);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -84,7 +86,6 @@ public class TheilSenEstimator extends Observable implements Algorithm {
|
|||
//damit eine initiale Ordnung herscht
|
||||
//Collections.sort(intervalIntersections);
|
||||
|
||||
interval = new Interval(NEGATIV_INF, POSITIV_INF);
|
||||
r = (double) n;
|
||||
while (true) {
|
||||
if (this.N <= n || (Math.abs(interval.getUpper() - interval.getLower())) < EPSILON) {
|
||||
|
|
|
@ -3,7 +3,7 @@ package presenter.algorithms.naiv;
|
|||
import model.Line;
|
||||
import model.Point;
|
||||
import presenter.algorithms.Algorithm;
|
||||
import presenter.algorithms.util.FastElementSelector;
|
||||
import presenter.util.FastElementSelector;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
|
|
|
@ -3,7 +3,7 @@ package presenter.algorithms.naiv;
|
|||
import model.Line;
|
||||
import model.Point;
|
||||
import presenter.algorithms.Algorithm;
|
||||
import presenter.algorithms.util.FastElementSelector;
|
||||
import presenter.util.FastElementSelector;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
|
|
@ -2,7 +2,7 @@ package presenter.algorithms.naiv;
|
|||
|
||||
import model.Line;
|
||||
import presenter.algorithms.Algorithm;
|
||||
import presenter.algorithms.util.FastElementSelector;
|
||||
import presenter.util.FastElementSelector;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
|
|
|
@ -9,7 +9,7 @@ import presenter.algorithms.advanced.TheilSenEstimator;
|
|||
import presenter.algorithms.naiv.NaivLeastMedianOfSquaresEstimator;
|
||||
import presenter.algorithms.naiv.NaivRepeatedMedianEstimator;
|
||||
import presenter.algorithms.naiv.NaivTheilSenEstimator;
|
||||
import presenter.algorithms.util.IntersectionComputer;
|
||||
import presenter.util.IntersectionComputer;
|
||||
import presenter.generator.DatasetGenerator;
|
||||
import presenter.io.DataImporter;
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package presenter.evaluation;
|
||||
|
||||
import model.Line;
|
||||
import presenter.algorithms.util.FastElementSelector;
|
||||
import presenter.util.FastElementSelector;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package presenter.evaluation;
|
||||
|
||||
import model.Line;
|
||||
import presenter.algorithms.util.FastElementSelector;
|
||||
import presenter.util.FastElementSelector;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package presenter.evaluation;
|
||||
|
||||
import model.Line;
|
||||
import presenter.algorithms.util.FastElementSelector;
|
||||
import presenter.util.FastElementSelector;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package presenter.algorithms.util;
|
||||
package presenter.util;
|
||||
|
||||
/**
|
||||
* Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden.
|
|
@ -1,4 +1,4 @@
|
|||
package presenter.algorithms.Comparators;
|
||||
package presenter.util.Comparators;
|
||||
|
||||
import model.Line;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package presenter.algorithms.Comparators;
|
||||
package presenter.util.Comparators;
|
||||
|
||||
import model.Line;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package presenter.algorithms.util;
|
||||
package presenter.util;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
|
@ -1,4 +1,4 @@
|
|||
package presenter.algorithms.util;
|
||||
package presenter.util;
|
||||
|
||||
import model.Interval;
|
||||
import model.Line;
|
||||
|
@ -99,7 +99,6 @@ public class IntersectionComputer {
|
|||
private void work(List<Line> lines, double lower, double higher) {
|
||||
IntersectionCounter counter = new IntersectionCounter();
|
||||
int count = counter.run(lines, new Interval(lower, higher));
|
||||
System.out.println("count: "+count);
|
||||
ArrayList<Point> points = counter.calculateIntersectionAbscissas();
|
||||
for (Point p : points) {
|
||||
if (!isFound(p)) {
|
|
@ -1,8 +1,8 @@
|
|||
package presenter.algorithms.util;
|
||||
package presenter.util;
|
||||
|
||||
import model.*;
|
||||
import presenter.algorithms.Comparators.YOrderLineComparatorBegin;
|
||||
import presenter.algorithms.Comparators.YOrderLineComparatorEnd;
|
||||
import presenter.util.Comparators.YOrderLineComparatorBegin;
|
||||
import presenter.util.Comparators.YOrderLineComparatorEnd;
|
||||
|
||||
import java.util.*;
|
||||
|
|
@ -1,10 +1,9 @@
|
|||
package presenter.algorithms.util;
|
||||
package presenter.util;
|
||||
|
||||
import model.Line;
|
||||
import model.Point;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
|
@ -1,13 +1,12 @@
|
|||
package presenter.algorithms;
|
||||
|
||||
package presenter.algorithms.advanced;
|
||||
|
||||
import model.Interval;
|
||||
import model.Line;
|
||||
import model.Point;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import presenter.algorithms.advanced.LeastMedianOfSquaresEstimator;
|
||||
import presenter.algorithms.util.IntersectionCounter;
|
||||
import presenter.util.IntersectionComputer;
|
||||
import presenter.util.IntersectionCounter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
|
@ -19,18 +18,19 @@ import static org.junit.Assert.*;
|
|||
*
|
||||
* @Author: Armin Wolf
|
||||
* @Email: a_wolf28@uni-muenster.de
|
||||
* @Date: 12.06.2017.
|
||||
* @Date: 23.10.2017.
|
||||
*/
|
||||
public class LeastMedianOfSquaresEstimatorTest {
|
||||
|
||||
private LeastMedianOfSquaresEstimator lms;
|
||||
private IntersectionComputer intersectionComputer;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
|
||||
public void setUp(){
|
||||
Double[] x = {18d, 24d, 30d, 34d, 38d};
|
||||
Double[] y = {18d, 26d, 30d, 40d, 70d};
|
||||
|
||||
|
||||
LinkedList<Line> lines = new LinkedList<>();
|
||||
ArrayList<Point> intersections = new ArrayList<>();
|
||||
|
||||
|
@ -38,36 +38,11 @@ public class LeastMedianOfSquaresEstimatorTest {
|
|||
lines.add(new Line(x[i], y[i]));
|
||||
}
|
||||
|
||||
intersectionComputer = new IntersectionComputer(lines);
|
||||
intersections = intersectionComputer.compute();
|
||||
lms = new LeastMedianOfSquaresEstimator(lines, intersections);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void approximateLMS() throws Exception {
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void mergeSort() throws Exception {
|
||||
// double[] umin = {6,3,4,1,2,5};
|
||||
// double[] umax = {3,5,2,6,1,4};
|
||||
double[] umin = {1, 2, 3, 4};
|
||||
double[] umax = {2, 3, 4, 1};
|
||||
ArrayList<Integer> a = new ArrayList<>();
|
||||
ArrayList<Integer> b = new ArrayList<>();
|
||||
|
||||
for (double d : umin) {
|
||||
a.add((int) d);
|
||||
}
|
||||
|
||||
for (double d : umax) {
|
||||
b.add((int) d);
|
||||
}
|
||||
IntersectionCounter invCounter = new IntersectionCounter();
|
||||
int ret = invCounter.run(a, b);
|
||||
assertEquals(3d, ret, 0.001);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void geEjValues() throws Exception {
|
||||
|
@ -115,5 +90,4 @@ public class LeastMedianOfSquaresEstimatorTest {
|
|||
assertTrue(interval.getActivity());
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
package presenter.algorithms.advanced;
|
||||
|
||||
import model.Line;
|
||||
import model.Point;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import presenter.util.IntersectionComputer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedList;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden.
|
||||
*
|
||||
* @Author: Armin Wolf
|
||||
* @Email: a_wolf28@uni-muenster.de
|
||||
* @Date: 23.10.2017.
|
||||
*/
|
||||
public class TheilSenEstimatorTest {
|
||||
|
||||
TheilSenEstimator estimator;
|
||||
IntersectionComputer intersectionComputer;
|
||||
|
||||
@Before
|
||||
public void setUp(){
|
||||
Double[] x = {18d, 24d, 30d, 34d, 38d};
|
||||
Double[] y = {18d, 26d, 30d, 40d, 70d};
|
||||
|
||||
|
||||
LinkedList<Line> lines = new LinkedList<>();
|
||||
ArrayList<Point> intersections = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < 5; i++) {
|
||||
lines.add(new Line(x[i], y[i]));
|
||||
}
|
||||
|
||||
intersectionComputer = new IntersectionComputer(lines);
|
||||
intersections = intersectionComputer.compute();
|
||||
estimator = new TheilSenEstimator(lines, intersections);
|
||||
}
|
||||
|
||||
|
||||
@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 {
|
||||
ArrayList<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);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
package presenter.io;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden.
|
||||
*
|
||||
* @Author: Armin Wolf
|
||||
* @Email: a_wolf28@uni-muenster.de
|
||||
* @Date: 21.06.2017.
|
||||
*/
|
||||
public class DataImporterTest {
|
||||
|
||||
private DataImporter importer;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
//importer = new DataImporter("C:\\Users\\Armin\\Desktop\\test.csv", null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void run() throws Exception {
|
||||
//importer.run();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
package presenter.util;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden.
|
||||
*
|
||||
* @Author: Armin Wolf
|
||||
* @Email: a_wolf28@uni-muenster.de
|
||||
* @Date: 23.10.2017.
|
||||
*/
|
||||
public class FastElementSelectorTest {
|
||||
|
||||
|
||||
@Test
|
||||
public void randomizedSelect() throws Exception {
|
||||
Double[] array = {1d, 2d, 3d, 4d};
|
||||
ArrayList<Double> list = new ArrayList<>(Arrays.asList(array));
|
||||
assertEquals(FastElementSelector.randomizedSelect(list, 0), 1d, 0.00001);
|
||||
assertEquals(FastElementSelector.randomizedSelect(list, 2), 2d, 0.00001);
|
||||
}
|
||||
|
||||
@Test(expected = IndexOutOfBoundsException.class)
|
||||
public void testIndexOutOfBoundsException() {
|
||||
ArrayList emptyList = new ArrayList();
|
||||
FastElementSelector.randomizedSelect(emptyList, 42);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
package presenter.util;
|
||||
|
||||
import model.Line;
|
||||
import model.LineModel;
|
||||
import model.Point;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden.
|
||||
*
|
||||
* @Author: Armin Wolf
|
||||
* @Email: a_wolf28@uni-muenster.de
|
||||
* @Date: 23.10.2017.
|
||||
*/
|
||||
public class IntersectionComputerTest {
|
||||
|
||||
private IntersectionComputer intersectionComputer;
|
||||
private LineModel lineModel;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
lineModel = new LineModel();
|
||||
lineModel.addLine(new Line(3,13,10,3));
|
||||
lineModel.addLine(new Line(1,9,1,9));
|
||||
lineModel.addLine(new Line(1,12,4,6));
|
||||
intersectionComputer = new IntersectionComputer(lineModel.getLines());
|
||||
}
|
||||
@Test
|
||||
public void compute() throws Exception {
|
||||
|
||||
ArrayList<Point> intersections = intersectionComputer.compute();
|
||||
double[] expectedX = {4.66, 7.11, 9.39};
|
||||
double[] expectedY = {4.66, 7.11, 5.52};
|
||||
|
||||
double[] actualX = new double[3];
|
||||
double[] actualY = new double[3];
|
||||
|
||||
for (int i=0;i<3;i++){
|
||||
actualX[i] = intersections.get(i).getX();
|
||||
actualY[i] = intersections.get(i).getY();
|
||||
}
|
||||
|
||||
Arrays.sort(expectedX);
|
||||
Arrays.sort(actualX);
|
||||
assertArrayEquals(expectedX, actualX, 0.01d);
|
||||
|
||||
Arrays.sort(expectedY);
|
||||
Arrays.sort(actualY);
|
||||
assertArrayEquals(expectedY, actualY, 0.01d);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
package presenter.util;
|
||||
|
||||
import model.Interval;
|
||||
import model.Line;
|
||||
import model.LineModel;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden.
|
||||
*
|
||||
* @Author: Armin Wolf
|
||||
* @Email: a_wolf28@uni-muenster.de
|
||||
* @Date: 23.10.2017.
|
||||
*/
|
||||
public class IntersectionCounterTest {
|
||||
|
||||
private IntersectionCounter intersectionCounter;
|
||||
private LineModel lineModel;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
intersectionCounter = new IntersectionCounter();
|
||||
lineModel = new LineModel();
|
||||
lineModel.addLine(new Line(3,13,10,3));
|
||||
lineModel.addLine(new Line(1,9,1,9));
|
||||
lineModel.addLine(new Line(1,12,4,6));
|
||||
for (Line l :lineModel.getLines()) {
|
||||
System.out.println("Steigung: "+l.getM()+"\t y-Achsenabschnitt: "+l.getB());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void run() throws Exception {
|
||||
assertEquals(3, intersectionCounter.run(lineModel.getLines(), new Interval(-9999,9999)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInversionInLists(){
|
||||
// double[] umin = {6,3,4,1,2,5};
|
||||
// double[] umax = {3,5,2,6,1,4};
|
||||
double[] umin = {1, 2, 3, 4};
|
||||
double[] umax = {2, 3, 4, 1};
|
||||
ArrayList<Integer> a = new ArrayList<>();
|
||||
ArrayList<Integer> b = new ArrayList<>();
|
||||
|
||||
for (double d : umin) {
|
||||
a.add((int) d);
|
||||
}
|
||||
|
||||
for (double d : umax) {
|
||||
b.add((int) d);
|
||||
}
|
||||
IntersectionCounter invCounter = new IntersectionCounter();
|
||||
int ret = invCounter.run(a, b);
|
||||
assertEquals(3d, ret, 0.001);
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue