diff --git a/client/pom.xml b/client/pom.xml index 1f1b532..e14b86d 100644 --- a/client/pom.xml +++ b/client/pom.xml @@ -57,6 +57,10 @@ org.slf4j slf4j-log4j12 + + junit + junit + org.controlsfx controlsfx diff --git a/client/src/main/java/ru/trader/controllers/SystemsEditorController.java b/client/src/main/java/ru/trader/controllers/SystemsEditorController.java index e12cd1e..ec22cd4 100644 --- a/client/src/main/java/ru/trader/controllers/SystemsEditorController.java +++ b/client/src/main/java/ru/trader/controllers/SystemsEditorController.java @@ -20,6 +20,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import ru.trader.model.MarketModel; import ru.trader.model.SystemModel; +import ru.trader.model.support.PositionComputer; import ru.trader.view.support.Localization; import ru.trader.view.support.cells.TextFieldCell; @@ -83,6 +84,13 @@ public class SystemsEditorController { clnS6.setCellFactory(TextFieldCell.forTableColumn(new DoubleStringConverter())); tblSystems.setItems(FXCollections.observableArrayList()); tblSystems.getSelectionModel().setCellSelectionEnabled(true); + tblSystems.setSortPolicy(t -> true); + system1.valueProperty().addListener((ov, o, n) -> clnS1.setText(n != null ? n.getName() : "")); + system2.valueProperty().addListener((ov, o, n) -> clnS2.setText(n != null ? n.getName() : "")); + system3.valueProperty().addListener((ov, o, n) -> clnS3.setText(n != null ? n.getName() : "")); + system4.valueProperty().addListener((ov, o, n) -> clnS4.setText(n != null ? n.getName() : "")); + system5.valueProperty().addListener((ov, o, n) -> clnS5.setText(n != null ? n.getName() : "")); + system6.valueProperty().addListener((ov, o, n) -> clnS6.setText(n != null ? n.getName() : "")); init(); } @@ -111,10 +119,33 @@ public class SystemsEditorController { reset(); } - public void add() { + public void add(){ tblSystems.getItems().add(new SystemData()); } + public void compute(){ + SystemModel sys1 = system1.getValue(); + SystemModel sys2 = system2.getValue(); + SystemModel sys3 = system3.getValue(); + SystemModel sys4 = system4.getValue(); + SystemModel sys5 = system5.getValue(); + SystemModel sys6 = system6.getValue(); + + for (SystemData systemData : tblSystems.getItems()) { + if (systemData.name.isEmpty().get()) continue; + PositionComputer computer = new PositionComputer(); + if (sys1 != null) computer.addLandMark(sys1, systemData.s1.get()); + if (sys2 != null) computer.addLandMark(sys2, systemData.s2.get()); + if (sys3 != null) computer.addLandMark(sys3, systemData.s3.get()); + if (sys4 != null) computer.addLandMark(sys4, systemData.s4.get()); + if (sys5 != null) computer.addLandMark(sys5, systemData.s5.get()); + if (sys6 != null) computer.addLandMark(sys6, systemData.s6.get()); + PositionComputer.Coordinates coord = computer.compute(); + systemData.x.set(coord.getX()); + systemData.y.set(coord.getY()); + systemData.z.set(coord.getZ()); + } + } private void commit(){ for (SystemData systemData : tblSystems.getItems()) { @@ -196,8 +227,12 @@ public class SystemsEditorController { return s6; } + public boolean isEmpty(){ + return name.get().isEmpty() || Double.isNaN(x.get()) || Double.isNaN(y.get()) || Double.isNaN(z.get()); + } + private void commit(){ - if (!name.get().isEmpty() && !Double.isNaN(x.get()) && !Double.isNaN(y.get()) && !Double.isNaN(z.get())){ + if (!isEmpty()){ if (system != null){ system.setName(name.get()); system.setPosition(x.get(), y.get(), z.get()); diff --git a/client/src/main/java/ru/trader/model/support/PositionComputer.java b/client/src/main/java/ru/trader/model/support/PositionComputer.java new file mode 100644 index 0000000..d076986 --- /dev/null +++ b/client/src/main/java/ru/trader/model/support/PositionComputer.java @@ -0,0 +1,125 @@ +package ru.trader.model.support; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import ru.trader.model.SystemModel; + +import java.util.ArrayList; +import java.util.List; + +public class PositionComputer { + private final static Logger LOG = LoggerFactory.getLogger(PositionComputer.class); + + private final static double MAX_ERROR = 1E-10; + private final static double MAX_VALUE = 1000; + private final static double MIN_VALUE = -1000; + + private final List marks = new ArrayList<>(6); + private final List distances = new ArrayList<>(6); + + public PositionComputer() { + } + + public void addLandMark(SystemModel system, double distance){ + marks.add(system); + distances.add(distance); + } + + + public Coordinates compute(){ + return compute(MIN_VALUE, MIN_VALUE, MIN_VALUE); + } + + public Coordinates compute(final double x, final double y, final double z){ + Coordinates res = new Coordinates(Double.NaN, Double.NaN, Double.NaN); + Coordinates current = new Coordinates(x, y, z); + double xmin = MIN_VALUE, xmax = MAX_VALUE; + double ymin = MIN_VALUE, ymax = MAX_VALUE; + double zmin = MIN_VALUE, zmax = MAX_VALUE; + double step=100, mineps = Double.NaN; + + while (true){ + double delta = 0; + for (int i = 0; i < marks.size(); i++) { + delta += Math.abs(marks.get(i).getDistance(current.x, current.y, current.z) - distances.get(i)); + } + LOG.trace("coordinates = {}, delta = {}", current, delta); + if (delta < MAX_ERROR) { + res = current; + LOG.debug("Coordinates found {}", res); + break; + } + if (Double.isNaN(mineps) || delta < mineps){ + mineps = delta; + res = new Coordinates(current); + } + + current.x += step; + if (current.x >= xmax){ + current.x = xmin; + current.y += step; + if (current.y >= ymax){ + current.y = ymin; + current.z += step; + if (current.z >= zmax){ + if (step < MAX_ERROR){ + LOG.debug("Coordinates not found, last {}, delta {}", res, mineps); + break; + } else { + xmin = res.x - step*2; xmax = res.x + step*2; current.x = xmin; + ymin = res.y - step*2; ymax = res.y + step*2; current.y = ymin; + zmin = res.z - step*2; zmax = res.z + step*2; current.z = zmin; + step = step/2; + LOG.trace("Change step to {}", step); + mineps = Double.NaN; + } + } + } + } + + } + + return res; + } + + + public class Coordinates { + private double x; + private double y; + private double z; + + public Coordinates(double x, double y, double z) { + this.x = x; + this.y = y; + this.z = z; + } + + public Coordinates(Coordinates other) { + this.x = other.x; + this.y = other.y; + this.z = other.z; + } + + public double getX() { + return x; + } + + public double getY() { + return y; + } + + public double getZ() { + return z; + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder("{"); + sb.append("x=").append(x); + sb.append(", y=").append(y); + sb.append(", z=").append(z); + sb.append('}'); + return sb.toString(); + } + } +} diff --git a/client/src/main/resources/view/sEditor.fxml b/client/src/main/resources/view/sEditor.fxml index c27279e..04ee54e 100644 --- a/client/src/main/resources/view/sEditor.fxml +++ b/client/src/main/resources/view/sEditor.fxml @@ -30,7 +30,16 @@ - + + + + + + diff --git a/client/src/test/java/ru/trader/model/support/PositionComputerTest.java b/client/src/test/java/ru/trader/model/support/PositionComputerTest.java new file mode 100644 index 0000000..81120fa --- /dev/null +++ b/client/src/test/java/ru/trader/model/support/PositionComputerTest.java @@ -0,0 +1,94 @@ +package ru.trader.model.support; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import ru.trader.core.Market; +import ru.trader.model.MarketModel; +import ru.trader.model.SystemModel; +import ru.trader.store.simple.SimpleMarket; + +public class PositionComputerTest extends Assert { + private final static Logger LOG = LoggerFactory.getLogger(PositionComputerTest.class); + private SystemModel system1; + private SystemModel system2; + private SystemModel system3; + private SystemModel system4; + private SystemModel system5; + private SystemModel system6; + private SystemModel system7; + private SystemModel system8; + + @Before + public void setUp() throws Exception { + LOG.info("Set up test compute"); + Market market = new SimpleMarket(); + market.addPlace("System1", -13.3438, 53.7812, 12.5625); + market.addPlace("System2", -7.9062, 34.7188, 2.125); + market.addPlace("System3", -4.8438, 26.6562, -4.7812); + market.addPlace("System4", -27.0938, 21.625, 0.7812); + market.addPlace("System5", -22.6875, 25.8125, -6.6875); + market.addPlace("System6", -106.25, 33.5938, -61); + market.addPlace("System7", -50.75, 50.0312, -13.2813); + market.addPlace("Sol", 0, 0, 0); + MarketModel marketModel = new MarketModel(market); + system1 = marketModel.systemsProperty().get(0); + system2 = marketModel.systemsProperty().get(1); + system3 = marketModel.systemsProperty().get(2); + system4 = marketModel.systemsProperty().get(3); + system5 = marketModel.systemsProperty().get(4); + system6 = marketModel.systemsProperty().get(5); + system7 = marketModel.systemsProperty().get(6); + system8 = marketModel.systemsProperty().get(7); + } + + @Test + public void testCompute() throws Exception { + LOG.info("Start test compute"); + PositionComputer computer = new PositionComputer(); + computer.addLandMark(system1, system1.getDistance(system7)); + computer.addLandMark(system2, system2.getDistance(system7)); + computer.addLandMark(system3, system3.getDistance(system7)); + computer.addLandMark(system4, system4.getDistance(system7)); + computer.addLandMark(system5, system5.getDistance(system7)); + computer.addLandMark(system6, system6.getDistance(system7)); + PositionComputer.Coordinates coordinates = computer.compute(); + assertEquals(system7.getX(), coordinates.getX(), 0.0000001); + assertEquals(system7.getY(), coordinates.getY(), 0.0000001); + assertEquals(system7.getZ(), coordinates.getZ(), 0.0000001); + } + + @Test + public void testCompute2() throws Exception { + LOG.info("Start test compute2"); + PositionComputer computer = new PositionComputer(); + computer.addLandMark(system1, system1.getDistance(system3)); + computer.addLandMark(system2, system2.getDistance(system3)); + computer.addLandMark(system7, system7.getDistance(system3)); + computer.addLandMark(system4, system4.getDistance(system3)); + computer.addLandMark(system5, system5.getDistance(system3)); + computer.addLandMark(system6, system6.getDistance(system3)); + PositionComputer.Coordinates coordinates = computer.compute(); + assertEquals(system3.getX(), coordinates.getX(), 0.0000001); + assertEquals(system3.getY(), coordinates.getY(), 0.0000001); + assertEquals(system3.getZ(), coordinates.getZ(), 0.0000001); + } + + @Test + public void testCompute3() throws Exception { + LOG.info("Start test compute3"); + PositionComputer computer = new PositionComputer(); + computer.addLandMark(system1, system1.getDistance(system8)); + computer.addLandMark(system2, system2.getDistance(system8)); + computer.addLandMark(system7, system7.getDistance(system8)); + computer.addLandMark(system4, system4.getDistance(system8)); + computer.addLandMark(system5, system5.getDistance(system8)); + computer.addLandMark(system6, system6.getDistance(system8)); + PositionComputer.Coordinates coordinates = computer.compute(); + assertEquals(system8.getX(), coordinates.getX(), 0.0000001); + assertEquals(system8.getY(), coordinates.getY(), 0.0000001); + assertEquals(system8.getZ(), coordinates.getZ(), 0.0000001); + } +} diff --git a/client/src/test/resources/log4j.properties b/client/src/test/resources/log4j.properties new file mode 100644 index 0000000..fe6a143 --- /dev/null +++ b/client/src/test/resources/log4j.properties @@ -0,0 +1,7 @@ +log4j.rootLogger = INFO, stdout + +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=%p: %d{dd.MM.yyyy HH:mm:ss} (%F:%L) - %m%n + +