diff --git a/client/src/main/java/ru/trader/Main.java b/client/src/main/java/ru/trader/Main.java index ce7644b..50dd561 100644 --- a/client/src/main/java/ru/trader/Main.java +++ b/client/src/main/java/ru/trader/Main.java @@ -101,6 +101,7 @@ public class Main extends Application { Screeners.loadItemAddStage(getUrl("itemAdd.fxml")); Screeners.loadGroupAddStage(getUrl("groupAdd.fxml")); Screeners.loadLoginStage(getUrl("login.fxml")); + Screeners.loadHelperStage(getUrl("helper.fxml")); } private static URL getUrl(String filename) throws MalformedURLException { diff --git a/client/src/main/java/ru/trader/controllers/HelperController.java b/client/src/main/java/ru/trader/controllers/HelperController.java new file mode 100644 index 0000000..babc0dc --- /dev/null +++ b/client/src/main/java/ru/trader/controllers/HelperController.java @@ -0,0 +1,87 @@ +package ru.trader.controllers; + +import javafx.beans.property.BooleanProperty; +import javafx.beans.property.IntegerProperty; +import javafx.beans.property.SimpleBooleanProperty; +import javafx.beans.property.SimpleIntegerProperty; +import javafx.beans.value.ChangeListener; +import javafx.fxml.FXML; +import javafx.scene.control.Label; +import javafx.scene.control.ListView; +import ru.trader.model.OrderModel; +import ru.trader.model.RouteEntryModel; +import ru.trader.model.RouteModel; +import ru.trader.view.support.ViewUtils; +import ru.trader.view.support.cells.OrderListCell; + + +public class HelperController { + + @FXML + private Label station; + @FXML + private Label system; + @FXML + private Label time; + @FXML + private Label refuel; + @FXML + private ListView buyOrders; + @FXML + private ListView sellOrders; + + + private RouteModel route; + private final BooleanProperty docked; + private final IntegerProperty currentEntry; + + public HelperController() { + currentEntry = new SimpleIntegerProperty(-1); + docked = new SimpleBooleanProperty(true); + } + + @FXML + private void initialize(){ + currentEntry.addListener(routeEntryListener); + buyOrders.setCellFactory(new OrderListCell(false)); + sellOrders.setCellFactory(new OrderListCell(true)); + } + + public void setRoute(RouteModel route) { + this.route = route; + currentEntry.setValue(0); + } + + private void setRouteEntry(int index){ + RouteEntryModel entry = route.get(index); + station.setText(entry.getStation().getName()); + system.setText(entry.getStation().getSystem().getName()); + time.setText(ViewUtils.timeToString(entry.getTime())); + refuel.setText(String.valueOf(entry.getRefill())); + buyOrders.setItems(entry.orders()); + sellOrders.setItems(entry.sellOrders()); + } + + @FXML + private void next(){ + int index = currentEntry.get(); + if (index < route.getJumps() - 1){ + currentEntry.setValue(index+1); + } + } + + @FXML + private void pause(){ + + } + + @FXML + private void previous(){ + int index = currentEntry.get(); + if (index > 0){ + currentEntry.setValue(index-1); + } + } + + private final ChangeListener routeEntryListener = (ov, o, n) -> ViewUtils.doFX(() -> setRouteEntry(n.intValue())); +} diff --git a/client/src/main/java/ru/trader/controllers/RouterController.java b/client/src/main/java/ru/trader/controllers/RouterController.java index 008a2f3..c3f868d 100644 --- a/client/src/main/java/ru/trader/controllers/RouterController.java +++ b/client/src/main/java/ru/trader/controllers/RouterController.java @@ -274,6 +274,7 @@ public class RouterController { if (path.isPresent()){ orders.addAll(path.get().getOrders()); addRouteToPath(path.get()); + Screeners.showHelper(path.get()); } }); } diff --git a/client/src/main/java/ru/trader/controllers/Screeners.java b/client/src/main/java/ru/trader/controllers/Screeners.java index 8cb1e4b..e9e4f00 100644 --- a/client/src/main/java/ru/trader/controllers/Screeners.java +++ b/client/src/main/java/ru/trader/controllers/Screeners.java @@ -33,6 +33,7 @@ public class Screeners { private static Parent itemAddScreen; private static Parent groupAddScreen; private static Parent loginScreen; + private static Parent helperScreen; private static MainController mainController; private static ItemDescController itemDescController; @@ -45,6 +46,7 @@ public class Screeners { private static ItemAddController itemAddController; private static GroupAddController groupAddController; private static LoginController loginController; + private static HelperController helperController; private static FXMLLoader initLoader(URL url){ FXMLLoader loader = new FXMLLoader(url, Localization.getResources()); @@ -104,8 +106,6 @@ public class Screeners { settingsScreen = loader.load(); addStylesheet(settingsScreen); settingsController = loader.getController(); - Stage stage = new Stage(); - stage.setScene(new Scene(settingsScreen)); } public static void loadSEditorStage(URL fxml) throws IOException { @@ -143,6 +143,13 @@ public class Screeners { loginController = loader.getController(); } + public static void loadHelperStage(URL fxml) throws IOException { + FXMLLoader loader = initLoader(fxml); + helperScreen = loader.load(); + addStylesheet(helperScreen); + helperController = loader.getController(); + } + public static void show(Node node){ mainController.getMainPane().setCenter(node); } @@ -239,6 +246,17 @@ public class Screeners { return dialog.showAndWait(); } + public static void showHelper(RouteModel route){ + helperController.setRoute(route); + if (helperScreen.getScene() == null){ + Stage stage = new Stage(); + stage.setScene(new Scene(helperScreen)); + stage.show(); + } else { + ((Stage)helperScreen.getScene().getWindow()).show(); + } + } + public static void reinitAll() { mainController.init(); systemsEditorController.init(); diff --git a/client/src/main/java/ru/trader/model/OfferModel.java b/client/src/main/java/ru/trader/model/OfferModel.java index 92461b3..8d93f1c 100644 --- a/client/src/main/java/ru/trader/model/OfferModel.java +++ b/client/src/main/java/ru/trader/model/OfferModel.java @@ -200,11 +200,11 @@ public class OfferModel { } public String toStationString(){ - return offer.toPString(); + return String.format("%.0f (%s - %s (%.0f Ls))", getPrice(), getSystem().getName(), getStation().getName(), getStation().getDistance()); } public String toItemString(){ - return offer.toIString(); + return String.format("%s (%.0f)", getItem().getName(), getPrice()); } public void refresh(){ diff --git a/client/src/main/java/ru/trader/model/OrderModel.java b/client/src/main/java/ru/trader/model/OrderModel.java index 93dac4f..2c7ffe1 100644 --- a/client/src/main/java/ru/trader/model/OrderModel.java +++ b/client/src/main/java/ru/trader/model/OrderModel.java @@ -1,6 +1,7 @@ package ru.trader.model; import javafx.beans.binding.Bindings; +import javafx.beans.binding.StringBinding; import javafx.beans.property.*; import javafx.beans.value.ObservableValue; import ru.trader.core.Order; @@ -153,4 +154,20 @@ public class OrderModel { } return distance; } + + public StringBinding asString(final boolean buy){ + if (buy){ + return Bindings.createStringBinding(() -> this.toString(buy), countProperty(), ModelBindings.offerPrice(buyOfferProperty(), true)); + } else { + return Bindings.createStringBinding(() -> this.toString(buy), countProperty(), priceProperty(), nameProperty()); + } + } + + public String toString(final boolean buy){ + if (buy){ + return String.format("%d x %s", getCount(), getBuyOffer().toItemString()); + } else { + return String.format("%d x %s", getCount(), getOffer().toItemString()); + } + } } diff --git a/client/src/main/java/ru/trader/model/RouteEntryModel.java b/client/src/main/java/ru/trader/model/RouteEntryModel.java new file mode 100644 index 0000000..b66a888 --- /dev/null +++ b/client/src/main/java/ru/trader/model/RouteEntryModel.java @@ -0,0 +1,71 @@ +package ru.trader.model; + +import javafx.beans.property.DoubleProperty; +import javafx.beans.property.ReadOnlyDoubleProperty; +import javafx.beans.property.SimpleDoubleProperty; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import ru.trader.analysis.RouteEntry; +import ru.trader.core.Order; +import ru.trader.model.support.BindingsHelper; + +import java.util.List; + +public class RouteEntryModel { + private final StationModel station; + private final RouteEntry entry; + private final DoubleProperty profit; + private final ObservableList orders; + private final ObservableList sellOrders; + + RouteEntryModel(RouteEntry entry, MarketModel market) { + this.entry = entry; + station = market.getModeler().get(entry.getVendor()); + List orderList = entry.getOrders(); + orders = BindingsHelper.observableList(orderList, market.getModeler()::get); + sellOrders = FXCollections.observableArrayList(); + profit = new SimpleDoubleProperty(); + profit.bind(BindingsHelper.group(Double::sum, OrderModel::profitProperty, orders)); + } + + void addSellOrder(OrderModel order){ + sellOrders.add(order); + } + + public StationModel getStation() { + return station; + } + + public double getProfit() { + return profit.get(); + } + + public ReadOnlyDoubleProperty profitProperty() { + return profit; + } + + public double getFuel(){ + return entry.getFuel(); + } + + public long getTime(){ + return entry.getTime(); + } + + public long getFullTime(){ + return entry.getFullTime(); + } + + public double getRefill(){ + return entry.getRefill(); + } + + public ObservableList orders() { + return orders; + } + + public ObservableList sellOrders() { + return sellOrders; + } + +} diff --git a/client/src/main/java/ru/trader/model/RouteModel.java b/client/src/main/java/ru/trader/model/RouteModel.java index bbf05c8..9531f04 100644 --- a/client/src/main/java/ru/trader/model/RouteModel.java +++ b/client/src/main/java/ru/trader/model/RouteModel.java @@ -1,37 +1,71 @@ package ru.trader.model; +import javafx.beans.property.DoubleProperty; +import javafx.beans.property.ReadOnlyDoubleProperty; +import javafx.beans.property.SimpleDoubleProperty; import ru.trader.analysis.Route; import ru.trader.analysis.RouteEntry; import ru.trader.core.Order; +import ru.trader.model.support.BindingsHelper; import java.util.ArrayList; import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; public class RouteModel { private final MarketModel market; private final Route _route; + private final DoubleProperty profit; + private final DoubleProperty profitByTime; + private final List entries; RouteModel(Route route, MarketModel market) { this.market = market; this._route = route; + entries = _route.getEntries().stream().map(e -> new RouteEntryModel(e, market)).collect(Collectors.toList()); + profit = new SimpleDoubleProperty(); + profit.bind(BindingsHelper.group(Double::sum, RouteEntryModel::profitProperty, entries)); + profitByTime = new SimpleDoubleProperty(); + profitByTime.bind(profit.divide(_route.getTime())); + fillSellOrders(); + } + + private void fillSellOrders(){ + for (int i = 0; i < entries.size(); i++) { + RouteEntryModel entry = entries.get(i); + for (OrderModel order : entry.orders()) { + for (int j = i+1; j < entries.size(); j++) { + RouteEntryModel buyEntry = entries.get(j); + if (buyEntry.getStation().equals(order.getBuyer())){ + buyEntry.addSellOrder(order); + break; + } + } + } + } + } + + public RouteEntryModel get(int index){ + return entries.get(index); } public double getDistance() { return _route.getDistance(); } - public double getTotalProfit() { - return _route.getProfit(); - } - public int getJumps() { - return _route.getLands(); + return entries.size(); } public int getRefuels() { return _route.getRefills(); } + public long getTime(){ + return _route.getTime(); + } + public Route getRoute() { return _route; } @@ -40,8 +74,20 @@ public class RouteModel { return _route.getLands(); } - public double getAvgProfit(){ - return _route.getProfit()/_route.getLands(); + public double getProfit() { + return profit.get(); + } + + public ReadOnlyDoubleProperty profitProperty() { + return profit; + } + + public double getProfitByTime(){ + return profitByTime.get(); + } + + public ReadOnlyDoubleProperty profitByTimeProperty(){ + return profitByTime; } public Collection getOrders(){ @@ -55,18 +101,21 @@ public class RouteModel { return res; } - public void add(OrderModel order){ + public RouteModel add(OrderModel order){ Route path = market._getPath(order); - if (path == null) return; + if (path == null) return this; _route.join(path); + return new RouteModel(_route, market); } - public void add(RouteModel route){ + public RouteModel add(RouteModel route){ _route.join(route.getRoute()); + return new RouteModel(_route, market); } - public void remove(OrderModel order) { + public RouteModel remove(OrderModel order) { _route.dropTo(order.getStation().getStation()); + return new RouteModel(_route, market); } } diff --git a/client/src/main/java/ru/trader/view/support/ViewUtils.java b/client/src/main/java/ru/trader/view/support/ViewUtils.java index 405a297..648afa1 100644 --- a/client/src/main/java/ru/trader/view/support/ViewUtils.java +++ b/client/src/main/java/ru/trader/view/support/ViewUtils.java @@ -41,4 +41,8 @@ public class ViewUtils { Platform.runLater(runnable); } } + + public static String timeToString(long time){ + return String.format("%d:%02d:%02d", time/3600, (time%3600)/60, (time%60)); + } } diff --git a/client/src/main/java/ru/trader/view/support/cells/OrderListCell.java b/client/src/main/java/ru/trader/view/support/cells/OrderListCell.java new file mode 100644 index 0000000..8a45e34 --- /dev/null +++ b/client/src/main/java/ru/trader/view/support/cells/OrderListCell.java @@ -0,0 +1,40 @@ +package ru.trader.view.support.cells; + +import javafx.scene.control.ListCell; +import javafx.scene.control.ListView; +import javafx.util.Callback; +import ru.trader.model.OrderModel; + +public class OrderListCell implements Callback, ListCell> { + private final boolean buy; + + public OrderListCell(boolean buy) { + this.buy = buy; + } + + @Override + public ListCell call(ListView param){ + return new ListCell(){ + private OrderModel o; + + @Override + public void updateItem(OrderModel order, boolean empty) { + super.updateItem(order, empty); + if (!empty){ + if (o != order){ + textProperty().unbind(); + textProperty().bind(order.asString(buy)); + o = order; + } + } else { + textProperty().unbind(); + o = null; + setText(null); + setGraphic(null); + } + } + + + }; + } +} diff --git a/client/src/main/resources/view/helper.fxml b/client/src/main/resources/view/helper.fxml new file mode 100644 index 0000000..1c3bfd5 --- /dev/null +++ b/client/src/main/resources/view/helper.fxml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/client/src/main/resources/view/paths.fxml b/client/src/main/resources/view/paths.fxml index f6ec245..b53abd5 100644 --- a/client/src/main/resources/view/paths.fxml +++ b/client/src/main/resources/view/paths.fxml @@ -33,18 +33,18 @@ - + - + - + - +