diff --git a/client/src/main/java/ru/trader/controllers/PathsController.java b/client/src/main/java/ru/trader/controllers/PathsController.java index 7073d49..40974ac 100644 --- a/client/src/main/java/ru/trader/controllers/PathsController.java +++ b/client/src/main/java/ru/trader/controllers/PathsController.java @@ -4,16 +4,11 @@ import javafx.collections.FXCollections; import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.scene.Parent; -import javafx.scene.control.TableColumn; import javafx.scene.control.TableView; -import javafx.scene.control.cell.TextFieldTableCell; -import javafx.util.converter.LongStringConverter; import org.controlsfx.control.ButtonBar; import org.controlsfx.control.action.AbstractAction; import org.controlsfx.control.action.Action; import org.controlsfx.dialog.Dialog; -import ru.trader.graph.PathRoute; -import ru.trader.model.OrderModel; import ru.trader.model.PathRouteModel; import java.util.Collection; @@ -42,7 +37,7 @@ public class PathsController { } - public void showDialog(Parent parent, Parent content, Collection paths) { + public PathRouteModel showDialog(Parent parent, Parent content, Collection paths) { init(paths); @@ -50,9 +45,12 @@ public class PathsController { dlg.setContent(content); dlg.getActions().addAll(OK, Dialog.Actions.CANCEL); dlg.setResizable(false); - dlg.show(); + return dlg.show() == OK ? getPath() : null; } + public PathRouteModel getPath(){ + return tblPaths.getSelectionModel().getSelectedItem(); + } private void init(Collection paths) { tblPaths.getSelectionModel().clearSelection(); diff --git a/client/src/main/java/ru/trader/controllers/RoutersController.java b/client/src/main/java/ru/trader/controllers/RoutersController.java index 1da29bd..8aaa81e 100644 --- a/client/src/main/java/ru/trader/controllers/RoutersController.java +++ b/client/src/main/java/ru/trader/controllers/RoutersController.java @@ -6,12 +6,11 @@ import javafx.collections.ListChangeListener; import javafx.fxml.FXML; import javafx.scene.control.Button; import javafx.scene.control.ComboBox; +import javafx.scene.control.ScrollPane; import javafx.scene.control.TableView; -import ru.trader.model.MarketModel; -import ru.trader.model.OfferDescModel; -import ru.trader.model.OrderModel; -import ru.trader.model.VendorModel; +import ru.trader.model.*; import ru.trader.view.support.NumberField; +import ru.trader.view.support.RouteNode; import java.util.Collection; @@ -30,6 +29,9 @@ public class RoutersController { @FXML private NumberField jumps; + @FXML + private ScrollPane path; + @FXML private Button add; @@ -60,9 +62,9 @@ public class RoutersController { balance.setValue(1000); cargo.setValue(4); - tank.setValue(30); + tank.setValue(20); distance.setValue(7); - jumps.setValue(4); + jumps.setValue(3); add.disableProperty().bind(this.balance.wrongProperty().or(this.cargo.wrongProperty())); tblOrders.setItems(FXCollections.observableArrayList()); @@ -87,7 +89,8 @@ public class RoutersController { market = MainController.getMarket(); source.setItems(market.vendorsProperty()); source.getSelectionModel().selectFirst(); - target.setItems(market.vendorsProperty()); + target.setItems(FXCollections.observableArrayList(market.vendorsProperty())); + target.getItems().add(0, null); tblOrders.getItems().clear(); totalBalance.setValue(balance.getValue()); totalProfit.setValue(0); @@ -129,6 +132,7 @@ public class RoutersController { tblOrders.getItems().clear(); totalBalance.setValue(balance.getValue()); totalProfit.setValue(0); + path.setContent(null); } @@ -139,14 +143,45 @@ public class RoutersController { } } + public void showOrders(){ + VendorModel s = source.getSelectionModel().getSelectedItem(); + VendorModel t = target.getSelectionModel().getSelectedItem(); + OrderModel order; + if (t==null){ + order = Screeners.showTopOrders(market.getOrders(s, totalBalance.getValue().doubleValue())); + } else { + order = Screeners.showTopOrders(market.getOrders(t, s, totalBalance.getValue().doubleValue())); + } + if (order!=null){ + tblOrders.getItems().add(order); + } + } + public void showRoutes(){ VendorModel s = source.getSelectionModel().getSelectedItem(); VendorModel t = target.getSelectionModel().getSelectedItem(); - if (t==null) return; - - MarketModel market = MainController.getMarket(); - Screeners.showRouters(market.getRouters(s, t, totalBalance.getValue().doubleValue())); + PathRouteModel path; + if (t==null){ + path = Screeners.showRouters(market.getRoutes(s, totalBalance.getValue().doubleValue())); + } else { + path = Screeners.showRouters(market.getRoutes(s, t, totalBalance.getValue().doubleValue())); + } + if (path!=null){ + tblOrders.getItems().addAll(path.getOrders()); + setPath(path); + } } + public void showTopRoutes(){ + PathRouteModel path = Screeners.showRouters(market.getTopRoutes(totalBalance.getValue().doubleValue())); + if (path!=null){ + tblOrders.getItems().addAll(path.getOrders()); + setPath(path); + } + } + + private void setPath(PathRouteModel route){ + path.setContent(new RouteNode(route).getNode()); + } } diff --git a/client/src/main/java/ru/trader/controllers/Screeners.java b/client/src/main/java/ru/trader/controllers/Screeners.java index 8f04c38..46c70eb 100644 --- a/client/src/main/java/ru/trader/controllers/Screeners.java +++ b/client/src/main/java/ru/trader/controllers/Screeners.java @@ -160,7 +160,7 @@ public class Screeners { return topOrdersController.showDialog(mainScreen, topOrdersScreen, top); } - public static void showRouters(ObservableList routers) { - pathsController.showDialog(mainScreen, pathsScreen, routers); + public static PathRouteModel showRouters(ObservableList routers) { + return pathsController.showDialog(mainScreen, pathsScreen, routers); } } diff --git a/client/src/main/java/ru/trader/model/MarketModel.java b/client/src/main/java/ru/trader/model/MarketModel.java index 5d72072..5db9613 100644 --- a/client/src/main/java/ru/trader/model/MarketModel.java +++ b/client/src/main/java/ru/trader/model/MarketModel.java @@ -3,11 +3,11 @@ package ru.trader.model; import javafx.beans.property.ListProperty; import javafx.beans.property.ReadOnlyListProperty; import javafx.beans.property.SimpleListProperty; -import javafx.collections.FXCollections; import javafx.collections.ObservableList; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import ru.trader.core.*; +import ru.trader.graph.PathRoute; import ru.trader.model.support.BindingsHelper; import ru.trader.model.support.ChangeMarketListener; @@ -169,15 +169,15 @@ public class MarketModel { return ModelFabrica.getModel(vendor, this); } - public ObservableList getTop(int limit, double balance){ - return BindingsHelper.observableList(analyzer.getTop(limit, balance), (o) -> { - OrderModel model = new OrderModel(asOfferDescModel(o.getSell()), balance, analyzer.getCargo()); - model.setBuyer(asModel(o.getBuy())); - model.setCount(model.getMax()); - return model; - }); + public OrderModel asModel(Order order) { + return new OrderModel(asOfferDescModel(order.getSell()), asModel(order.getBuy()), order.getCount()); } + public PathRouteModel asModel(PathRoute path) { + return new PathRouteModel(path, this); + } + + public void setCargo(long cargo){ analyzer.setCargo(cargo); } @@ -194,7 +194,28 @@ public class MarketModel { analyzer.setMaxDistance(distance); } - public ObservableList getRouters(VendorModel from, VendorModel to, double balance){ - return BindingsHelper.observableList(analyzer.getPaths(from.getVendor(), to.getVendor(), balance), PathRouteModel::new); + public ObservableList getOrders(VendorModel from, double balance) { + return BindingsHelper.observableList(analyzer.getOrders(from.getVendor(), balance), this::asModel); } + + public ObservableList getOrders(VendorModel from, VendorModel to, double balance) { + return BindingsHelper.observableList(analyzer.getOrders(from.getVendor(), to.getVendor(), balance), this::asModel); + } + + public ObservableList getTop(int limit, double balance){ + return BindingsHelper.observableList(analyzer.getTop(limit, balance), this::asModel); + } + + public ObservableList getRoutes(VendorModel from, double balance){ + return BindingsHelper.observableList(analyzer.getPaths(from.getVendor(), balance), this::asModel); + } + + public ObservableList getRoutes(VendorModel from, VendorModel to, double balance){ + return BindingsHelper.observableList(analyzer.getPaths(from.getVendor(), to.getVendor(), balance), this::asModel); + } + + public ObservableList getTopRoutes(double balance){ + return BindingsHelper.observableList(analyzer.getTopPaths(100, balance), this::asModel); + } + } diff --git a/client/src/main/java/ru/trader/model/OrderModel.java b/client/src/main/java/ru/trader/model/OrderModel.java index d3312fb..6c77184 100644 --- a/client/src/main/java/ru/trader/model/OrderModel.java +++ b/client/src/main/java/ru/trader/model/OrderModel.java @@ -31,6 +31,13 @@ public class OrderModel { }; } + public OrderModel(OfferDescModel sellOffer, OfferModel buyOffer, long max) { + this(sellOffer); + this.max = max; + setBuyer(buyOffer); + setCount(max); + } + public OrderModel(OfferDescModel offer, double balance, long limit) { this(offer); this.max = Math.min(limit, (long) Math.floor(balance / offer.getPrice())); diff --git a/client/src/main/java/ru/trader/model/PathRouteModel.java b/client/src/main/java/ru/trader/model/PathRouteModel.java index 48f9f92..4c564fc 100644 --- a/client/src/main/java/ru/trader/model/PathRouteModel.java +++ b/client/src/main/java/ru/trader/model/PathRouteModel.java @@ -1,28 +1,35 @@ package ru.trader.model; -import ru.trader.core.Vendor; +import ru.trader.core.Order; import ru.trader.graph.PathRoute; +import java.util.ArrayList; +import java.util.Collection; + public class PathRouteModel { + private final MarketModel market; private final double distance; private final double totalProfit; private final int jumps; private final int refuels; + private final int lands; private final PathRoute path; - public PathRouteModel(PathRoute path) { + PathRouteModel(PathRoute path, MarketModel market) { + this.market = market; this.path = path; PathRoute p = path.getRoot(); - double pr =0, d = 0; int j = 0, r = 0; + totalProfit = p.getProfit(); + double d = 0; int j = 0, r = 0, l = 0; while (p.hasNext()){ p = p.getNext(); - d += path.getDistance(); - pr += p.getMaxProfit(); + d += p.getDistance(); j++; if (p.isRefill()) r++; + if (p.getBest() != null || p.isRefill()) l++; } - totalProfit = pr; + lands = l; distance = d; jumps = j; refuels = r; @@ -47,4 +54,29 @@ public class PathRouteModel { public PathRoute getPath() { return path; } + + public int getLands() { + return lands; + } + + public double getAvgProfit(){ + return totalProfit/lands; + } + + public Collection getOrders(){ + Collection res = new ArrayList<>(lands); + PathRoute p = path.getRoot(); + Order cargo = null; + while (p.hasNext()){ + p = p.getNext(); + if (cargo == null && p.getBest()!=null){ + cargo = p.getBest(); + res.add(market.asModel(cargo)); + } + if (cargo!=null && cargo.isBuyer(p.get())){ + cargo = null; + } + } + return res; + } } diff --git a/client/src/main/java/ru/trader/view/support/RouteNode.java b/client/src/main/java/ru/trader/view/support/RouteNode.java new file mode 100644 index 0000000..879daf4 --- /dev/null +++ b/client/src/main/java/ru/trader/view/support/RouteNode.java @@ -0,0 +1,86 @@ +package ru.trader.view.support; + +import javafx.scene.Node; +import javafx.scene.layout.HBox; +import javafx.scene.layout.Priority; +import javafx.scene.layout.VBox; +import javafx.scene.text.Text; +import org.controlsfx.glyphfont.GlyphFontRegistry; +import ru.trader.core.Order; +import ru.trader.graph.PathRoute; +import ru.trader.model.PathRouteModel; + +public class RouteNode { + private final static String CSS_PATH = "path"; + private final static String CSS_ICONS = "path-icons"; + private final static String CSS_TRACK = "path-track"; + private final static String CSS_TRACK_TEXT = "path-track-text"; + private final static String CSS_VENDOR = "path-vendor"; + + private final PathRoute path; + private final HBox node = new HBox(); + + public RouteNode(PathRouteModel path) { + this.path = path.getPath(); + node.getStyleClass().add(CSS_PATH); + build(); + } + + private void build(){ + HBox v = new HBox(); + VBox icons = new VBox(); + VBox track = new VBox(); + VBox.setVgrow(track, Priority.ALWAYS); + VBox.setVgrow(icons, Priority.ALWAYS); + + v.getStyleClass().add(CSS_VENDOR); + icons.getStyleClass().add(CSS_ICONS); + track.getStyleClass().add(CSS_TRACK); + + PathRoute p = path.getRoot(); + + v.getChildren().add(new Text(p.get().getName())); + Order cargo = null; + while (p.hasNext()){ + p = p.getNext(); + if (cargo == null && p.getBest() != null){ + cargo = p.getBest(); + icons.getChildren().add(GlyphFontRegistry.glyph("FontAwesome|UPLOAD_ALT")); + } + if (p.isRefill()) icons.getChildren().add(GlyphFontRegistry.glyph("FontAwesome|REFRESH")); + + node.getChildren().addAll(v, icons); + + Text t = new Text(String.format("(%.2f LY)", p.getDistance())); + t.getStyleClass().add(CSS_TRACK_TEXT); + + + track.getChildren().addAll(t, GlyphFontRegistry.glyph("FontAwesome|LONG_ARROW_RIGHT")); + + node.getChildren().addAll(track); + + v = new HBox(); + icons = new VBox(); + track = new VBox(0); + VBox.setVgrow(track, Priority.ALWAYS); + VBox.setVgrow(icons, Priority.ALWAYS); + + v.getStyleClass().add(CSS_VENDOR); + icons.getStyleClass().add(CSS_ICONS); + track.getStyleClass().add(CSS_TRACK); + + v.getChildren().add(new Text(p.get().getName())); + v.getChildren().add(icons); + if (cargo != null && cargo.isBuyer(p.get())){ + v.getChildren().add(new Text(String.format(" (%+.0f) ", cargo.getProfit()))); + cargo = null; + icons.getChildren().add(GlyphFontRegistry.glyph("FontAwesome|DOWNLOAD_ALT")); + } + } + node.getChildren().addAll(v, icons); + } + + public Node getNode() { + return node; + } +} diff --git a/client/src/main/java/ru/trader/view/support/cells/PathRouteCell.java b/client/src/main/java/ru/trader/view/support/cells/PathRouteCell.java index ecf07b2..3d0dc30 100644 --- a/client/src/main/java/ru/trader/view/support/cells/PathRouteCell.java +++ b/client/src/main/java/ru/trader/view/support/cells/PathRouteCell.java @@ -1,49 +1,25 @@ package ru.trader.view.support.cells; -import javafx.geometry.Pos; import javafx.scene.control.TableCell; import javafx.scene.control.TableColumn; -import javafx.scene.layout.HBox; -import javafx.scene.layout.VBox; -import javafx.scene.text.Text; +import javafx.scene.control.TableRow; import javafx.util.Callback; -import org.controlsfx.glyphfont.GlyphFontRegistry; -import ru.trader.core.Order; -import ru.trader.graph.PathRoute; import ru.trader.model.PathRouteModel; +import ru.trader.view.support.RouteNode; public class PathRouteCell implements Callback, TableCell> { + @Override public TableCell call(TableColumn param) { return new TableCell(){ @Override public void updateItem(T value, boolean empty) { super.updateItem(value, empty); - if (!empty){ - PathRoute p = ((PathRouteModel) getTableRow().getItem()).getPath().getRoot(); - HBox hBox = new HBox(); - - HBox v = new HBox(); - v.setAlignment(Pos.BOTTOM_CENTER); - v.getChildren().add(new Text(p.get().getName())); - while (p.hasNext()){ - p = p.getNext(); - if (p.isRefill()) v.getChildren().add(GlyphFontRegistry.glyph("FontAwesome|REFRESH")); - hBox.getChildren().add(v); - - VBox dist = new VBox(new Text(String.format("(%+.0f LY)", p.getDistance()))); - dist.setAlignment(Pos.BASELINE_CENTER); - dist.getChildren().add(GlyphFontRegistry.glyph("FontAwesome|LONG_ARROW_RIGHT")); - hBox.getChildren().addAll(dist); - - v = new HBox(); - v.setAlignment(Pos.BOTTOM_CENTER); - v.getChildren().add(new Text(p.get().getName())); - v.getChildren().add(new Text(String.format(" (%+.0f) ", p.getMaxProfit()))); - } - hBox.getChildren().add(v); + TableRow row = getTableRow(); + if (!empty && row !=null && row.getItem() != null){ + RouteNode route = new RouteNode((PathRouteModel) row.getItem()); setText(null); - setGraphic(hBox); + setGraphic(route.getNode()); } else { setText(null); setGraphic(null); diff --git a/client/src/main/resources/view/offers.fxml b/client/src/main/resources/view/offers.fxml index c2719a0..c0941f8 100644 --- a/client/src/main/resources/view/offers.fxml +++ b/client/src/main/resources/view/offers.fxml @@ -11,7 +11,7 @@ - + diff --git a/client/src/main/resources/view/paths.fxml b/client/src/main/resources/view/paths.fxml index 467dbbf..5130d1b 100644 --- a/client/src/main/resources/view/paths.fxml +++ b/client/src/main/resources/view/paths.fxml @@ -12,34 +12,38 @@ + prefWidth="1050"> - + - - - - - - + - - + + + + + + + - + + + + + - + diff --git a/client/src/main/resources/view/routers.fxml b/client/src/main/resources/view/routers.fxml index 42c49fc..0dfacc9 100644 --- a/client/src/main/resources/view/routers.fxml +++ b/client/src/main/resources/view/routers.fxml @@ -22,13 +22,13 @@ @@ -42,18 +42,22 @@