add top orders
This commit is contained in:
@@ -65,6 +65,7 @@ public class Main extends Application {
|
|||||||
Screeners.loadVEditorStage(getUrl(("vEditor.fxml")));
|
Screeners.loadVEditorStage(getUrl(("vEditor.fxml")));
|
||||||
Screeners.loadAddOfferStage(getUrl(("oEditor.fxml")));
|
Screeners.loadAddOfferStage(getUrl(("oEditor.fxml")));
|
||||||
Screeners.loadOrdersStage(getUrl(("orders.fxml")));
|
Screeners.loadOrdersStage(getUrl(("orders.fxml")));
|
||||||
|
Screeners.loadTopOrdersStage(getUrl(("topOrders.fxml")));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static URL getUrl(String filename) throws MalformedURLException {
|
private static URL getUrl(String filename) throws MalformedURLException {
|
||||||
|
|||||||
@@ -94,14 +94,14 @@ public class RoutersController {
|
|||||||
vendors.getSelectionModel().select(order.getVendor());
|
vendors.getSelectionModel().select(order.getVendor());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addOrders(ActionEvent e){
|
public void addOrders(){
|
||||||
Collection<OrderModel> orders = Screeners.showOrders(getOffers(), totalBalance.getValue().doubleValue(), cargo.getValue().longValue());
|
Collection<OrderModel> orders = Screeners.showOrders(getOffers(), totalBalance.getValue().doubleValue(), cargo.getValue().longValue());
|
||||||
if (orders!=null){
|
if (orders!=null){
|
||||||
tblOrders.getItems().addAll(orders);
|
tblOrders.getItems().addAll(orders);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeSelected(ActionEvent e){
|
public void removeSelected(){
|
||||||
TableView.TableViewSelectionModel<OrderModel> select = tblOrders.getSelectionModel();
|
TableView.TableViewSelectionModel<OrderModel> select = tblOrders.getSelectionModel();
|
||||||
if (!select.isEmpty()){
|
if (!select.isEmpty()){
|
||||||
int index = select.getSelectedIndex();
|
int index = select.getSelectedIndex();
|
||||||
@@ -109,8 +109,17 @@ public class RoutersController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeAll(ActionEvent e){
|
public void removeAll(){
|
||||||
tblOrders.getItems().clear();
|
tblOrders.getItems().clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void showTopOrders(){
|
||||||
|
MarketModel market = MainController.getMarket();
|
||||||
|
OrderModel order = Screeners.showTopOrders(market.getTop(100, totalBalance.getValue().doubleValue(), cargo.getValue().longValue()));
|
||||||
|
if (order!=null){
|
||||||
|
tblOrders.getItems().add(order);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package ru.trader.controllers;
|
package ru.trader.controllers;
|
||||||
|
|
||||||
|
import javafx.collections.ObservableList;
|
||||||
import javafx.fxml.FXMLLoader;
|
import javafx.fxml.FXMLLoader;
|
||||||
import javafx.scene.Node;
|
import javafx.scene.Node;
|
||||||
import javafx.scene.Parent;
|
import javafx.scene.Parent;
|
||||||
@@ -22,12 +23,14 @@ public class Screeners {
|
|||||||
private static Parent vEditorScreen;
|
private static Parent vEditorScreen;
|
||||||
private static Parent editOffersScreen;
|
private static Parent editOffersScreen;
|
||||||
private static Parent ordersScreen;
|
private static Parent ordersScreen;
|
||||||
|
private static Parent topOrdersScreen;
|
||||||
|
|
||||||
private static MainController mainController;
|
private static MainController mainController;
|
||||||
private static ItemDescController itemDescController;
|
private static ItemDescController itemDescController;
|
||||||
private static VendorEditorController vEditorController;
|
private static VendorEditorController vEditorController;
|
||||||
private static OffersEditorController oEditorController;
|
private static OffersEditorController oEditorController;
|
||||||
private static OrdersController ordersController;
|
private static OrdersController ordersController;
|
||||||
|
private static TopOrdersController topOrdersController;
|
||||||
|
|
||||||
private static FXMLLoader initLoader(URL url){
|
private static FXMLLoader initLoader(URL url){
|
||||||
FXMLLoader loader = new FXMLLoader(url);
|
FXMLLoader loader = new FXMLLoader(url);
|
||||||
@@ -82,6 +85,15 @@ public class Screeners {
|
|||||||
stage.setScene(new Scene(ordersScreen));
|
stage.setScene(new Scene(ordersScreen));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void loadTopOrdersStage(URL fxml) throws IOException {
|
||||||
|
FXMLLoader loader = initLoader(fxml);
|
||||||
|
topOrdersScreen = loader.load();
|
||||||
|
addStylesheet(topOrdersScreen);
|
||||||
|
topOrdersController = loader.getController();
|
||||||
|
Stage stage = new Stage();
|
||||||
|
stage.setScene(new Scene(topOrdersScreen));
|
||||||
|
}
|
||||||
|
|
||||||
public static void show(Node node){
|
public static void show(Node node){
|
||||||
mainController.getMainPane().setCenter(node);
|
mainController.getMainPane().setCenter(node);
|
||||||
}
|
}
|
||||||
@@ -132,4 +144,8 @@ public class Screeners {
|
|||||||
public static void closeAll() {
|
public static void closeAll() {
|
||||||
itemDescController.close();
|
itemDescController.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static OrderModel showTopOrders(ObservableList<OrderModel> top) {
|
||||||
|
return topOrdersController.showDialog(mainScreen, topOrdersScreen, top);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,71 @@
|
|||||||
|
package ru.trader.controllers;
|
||||||
|
|
||||||
|
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.model.OrderModel;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
public class TopOrdersController {
|
||||||
|
private final Action OK = new AbstractAction("OK") {
|
||||||
|
{
|
||||||
|
ButtonBar.setType(this, ButtonBar.ButtonType.OK_DONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(ActionEvent event) {
|
||||||
|
Dialog dlg = (Dialog) event.getSource();
|
||||||
|
dlg.hide();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private TableView<OrderModel> tblOrders;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private TableColumn<OrderModel, Long> count;
|
||||||
|
|
||||||
|
private OrderModel order;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private void initialize() {
|
||||||
|
count.setCellFactory(TextFieldTableCell.forTableColumn(new LongStringConverter()));
|
||||||
|
tblOrders.getSelectionModel().selectedItemProperty().addListener((v, o, n) -> changeOrder(n));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public OrderModel showDialog(Parent parent, Parent content, Collection<OrderModel> orders) {
|
||||||
|
|
||||||
|
init(orders);
|
||||||
|
|
||||||
|
Dialog dlg = new Dialog(parent, "TOP заказов");
|
||||||
|
dlg.setContent(content);
|
||||||
|
dlg.getActions().addAll(OK, Dialog.Actions.CANCEL);
|
||||||
|
dlg.setResizable(false);
|
||||||
|
return dlg.show() == OK ? order : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void init(Collection<OrderModel> orders) {
|
||||||
|
tblOrders.getSelectionModel().clearSelection();
|
||||||
|
tblOrders.setItems(FXCollections.observableArrayList(orders));
|
||||||
|
if (tblOrders.getSortOrder().size()>0)
|
||||||
|
tblOrders.sort();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void changeOrder(OrderModel order) {
|
||||||
|
this.order = order;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@ import javafx.beans.property.ListProperty;
|
|||||||
import javafx.beans.property.ReadOnlyListProperty;
|
import javafx.beans.property.ReadOnlyListProperty;
|
||||||
import javafx.beans.property.SimpleListProperty;
|
import javafx.beans.property.SimpleListProperty;
|
||||||
import javafx.collections.FXCollections;
|
import javafx.collections.FXCollections;
|
||||||
|
import javafx.collections.ObservableList;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import ru.trader.core.*;
|
import ru.trader.core.*;
|
||||||
@@ -157,5 +158,13 @@ public class MarketModel {
|
|||||||
return ModelFabrica.getModel(vendor, this);
|
return ModelFabrica.getModel(vendor, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ObservableList<OrderModel> getTop(int limit, double balance, long max){
|
||||||
|
return BindingsHelper.observableList(market.getTop(limit, balance, max), (o) -> {
|
||||||
|
OrderModel model = new OrderModel(asOfferDescModel(o.getSell()), balance, max);
|
||||||
|
model.setBuyer(asModel(o.getBuy()));
|
||||||
|
model.setCount(model.getMax());
|
||||||
|
return model;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,11 +28,16 @@
|
|||||||
<Label text="Станция:" GridPane.rowIndex="2"/>
|
<Label text="Станция:" GridPane.rowIndex="2"/>
|
||||||
<ComboBox fx:id="vendors" prefWidth="160" GridPane.columnIndex="1" GridPane.rowIndex="2"/>
|
<ComboBox fx:id="vendors" prefWidth="160" GridPane.columnIndex="1" GridPane.rowIndex="2"/>
|
||||||
<Separator GridPane.columnSpan="2" GridPane.rowIndex="3" GridPane.margin="$separator_margin"/>
|
<Separator GridPane.columnSpan="2" GridPane.rowIndex="3" GridPane.margin="$separator_margin"/>
|
||||||
<HBox GridPane.columnSpan="2" GridPane.rowIndex="4" alignment="CENTER" spacing="5">
|
<VBox GridPane.columnSpan="2" GridPane.rowIndex="4" spacing="20">
|
||||||
|
<HBox alignment="CENTER" spacing="5">
|
||||||
<Button fx:id="add" text="Добавить" onAction="#addOrders"/>
|
<Button fx:id="add" text="Добавить" onAction="#addOrders"/>
|
||||||
<Button text="Удалить" onAction="#removeSelected"/>
|
<Button text="Удалить" onAction="#removeSelected"/>
|
||||||
<Button text="Очистить" onAction="#removeAll" />
|
<Button text="Очистить" onAction="#removeAll" />
|
||||||
</HBox>
|
</HBox>
|
||||||
|
<HBox alignment="CENTER" spacing="5">
|
||||||
|
<Button text="TOP 100" onAction="#showTopOrders" />
|
||||||
|
</HBox>
|
||||||
|
</VBox>
|
||||||
</GridPane>
|
</GridPane>
|
||||||
</TitledPane>
|
</TitledPane>
|
||||||
<Pane VBox.vgrow="ALWAYS"/>
|
<Pane VBox.vgrow="ALWAYS"/>
|
||||||
|
|||||||
41
client/src/main/resources/view/topOrders.fxml
Normal file
41
client/src/main/resources/view/topOrders.fxml
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<?import javafx.scene.control.cell.*?>
|
||||||
|
<?import javafx.scene.layout.*?>
|
||||||
|
<?import javafx.scene.control.*?>
|
||||||
|
|
||||||
|
|
||||||
|
<?import ru.trader.view.support.cells.DoubleCell?>
|
||||||
|
|
||||||
|
<?import ru.trader.view.support.cells.OfferCellValueImpl?>
|
||||||
|
<?import ru.trader.view.support.cells.OfferTableCell?>
|
||||||
|
<HBox xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1"
|
||||||
|
fx:controller="ru.trader.controllers.TopOrdersController" styleClass="dialog"
|
||||||
|
prefWidth="555">
|
||||||
|
<TableView fx:id="tblOrders" editable="true">
|
||||||
|
<columns>
|
||||||
|
<TableColumn minWidth="160.0" text="Товар">
|
||||||
|
<cellValueFactory><PropertyValueFactory property="name"/></cellValueFactory>
|
||||||
|
</TableColumn>
|
||||||
|
<TableColumn minWidth="120.0" text="Продавец">
|
||||||
|
<cellValueFactory><OfferCellValueImpl property="offer"/></cellValueFactory>
|
||||||
|
</TableColumn>
|
||||||
|
<TableColumn fx:id="count" minWidth="60.0" text="Кол-во">
|
||||||
|
<cellValueFactory><PropertyValueFactory property="count"/></cellValueFactory>
|
||||||
|
</TableColumn>
|
||||||
|
<TableColumn minWidth="120.0" text="Покупатель">
|
||||||
|
<cellValueFactory><OfferCellValueImpl property="buyer"/></cellValueFactory>
|
||||||
|
</TableColumn>
|
||||||
|
<TableColumn fx:id="profit" minWidth="80.0" text="Прибыль" sortType="DESCENDING">
|
||||||
|
<cellFactory><DoubleCell/></cellFactory>
|
||||||
|
<cellValueFactory><PropertyValueFactory property="profit"/></cellValueFactory>
|
||||||
|
</TableColumn>
|
||||||
|
</columns>
|
||||||
|
<columnResizePolicy>
|
||||||
|
<TableView fx:constant="UNCONSTRAINED_RESIZE_POLICY"/>
|
||||||
|
</columnResizePolicy>
|
||||||
|
<sortOrder>
|
||||||
|
<fx:reference source="profit"/>
|
||||||
|
</sortOrder>
|
||||||
|
</TableView>
|
||||||
|
</HBox>
|
||||||
@@ -3,10 +3,7 @@ package ru.trader.core;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.TreeSet;
|
|
||||||
|
|
||||||
public class ItemStat {
|
public class ItemStat {
|
||||||
private final static Logger LOG = LoggerFactory.getLogger(ItemStat.class);
|
private final static Logger LOG = LoggerFactory.getLogger(ItemStat.class);
|
||||||
@@ -85,8 +82,8 @@ public class ItemStat {
|
|||||||
return offers.size();
|
return offers.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection<Offer> getOffers() {
|
public NavigableSet<Offer> getOffers() {
|
||||||
return Collections.unmodifiableCollection(offers);
|
return Collections.unmodifiableNavigableSet(offers);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Offer getMin() {
|
public Offer getMin() {
|
||||||
|
|||||||
@@ -41,4 +41,6 @@ public interface Market {
|
|||||||
void updatePrice(Offer offer, double price);
|
void updatePrice(Offer offer, double price);
|
||||||
|
|
||||||
void setChange(boolean change);
|
void setChange(boolean change);
|
||||||
|
|
||||||
|
Collection<Order> getTop(int limit, double balance, long max);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -148,5 +148,40 @@ public abstract class MarketSupport implements Market {
|
|||||||
public void setChange(boolean change) {
|
public void setChange(boolean change) {
|
||||||
this.change = change;
|
this.change = change;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<Order> getTop(int limit, double balance, long max){
|
||||||
|
LOG.debug("Get top {}", limit);
|
||||||
|
TreeSet<Order> top = new TreeSet<>();
|
||||||
|
for (Vendor vendor : getVendors()) {
|
||||||
|
LOG.debug("Check vendor {}", vendor);
|
||||||
|
for (Offer sell : vendor.getAllSellOffers()) {
|
||||||
|
long count = Math.min(max, (long) Math.floor(balance / sell.getPrice()));
|
||||||
|
LOG.debug("Sell offer {}, count = {}", sell, count);
|
||||||
|
if (count == 0) continue;
|
||||||
|
Iterator<Offer> buyers = getStatBuy(sell.getItem()).getOffers().descendingIterator();
|
||||||
|
while (buyers.hasNext()){
|
||||||
|
Offer buy = buyers.next();
|
||||||
|
Order order = new Order(sell, buy, count);
|
||||||
|
LOG.debug("Buy offer {} profit = {}", buy, order.getProfit());
|
||||||
|
if (order.getProfit() <= 0 ) break;
|
||||||
|
if (top.size() == limit){
|
||||||
|
LOG.debug("Min order {}", top.first());
|
||||||
|
if (top.first().getProfit() < order.getProfit()) {
|
||||||
|
LOG.debug("Add to top");
|
||||||
|
top.add(order);
|
||||||
|
top.pollFirst();
|
||||||
|
} else {
|
||||||
|
LOG.debug("Is low profit, skip");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
top.add(order);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return top;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
76
core/src/main/java/ru/trader/core/Order.java
Normal file
76
core/src/main/java/ru/trader/core/Order.java
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
package ru.trader.core;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
public class Order implements Comparable<Order> {
|
||||||
|
private Offer sell;
|
||||||
|
private Offer buy;
|
||||||
|
private double profit;
|
||||||
|
|
||||||
|
public Order(Offer sell, Offer buy, long count) {
|
||||||
|
this.sell = sell;
|
||||||
|
this.buy = buy;
|
||||||
|
this.profit = (buy.getPrice() - sell.getPrice()) * count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Offer getSell() {
|
||||||
|
return sell;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Offer getBuy() {
|
||||||
|
return buy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getProfit(){
|
||||||
|
return profit;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(@NotNull Order order) {
|
||||||
|
Objects.requireNonNull(order, "Not compare with null");
|
||||||
|
if (this == order) return 0;
|
||||||
|
int cmp = Double.compare(profit, order.profit);
|
||||||
|
if (cmp!=0) return cmp;
|
||||||
|
cmp = Double.compare(sell.getPrice(), order.sell.getPrice());
|
||||||
|
if (cmp!=0) return cmp;
|
||||||
|
cmp = Double.compare(order.buy.getPrice(), buy.getPrice());
|
||||||
|
if (cmp!=0) return cmp;
|
||||||
|
cmp = sell.compareTo(order.sell);
|
||||||
|
if (cmp!=0) return cmp;
|
||||||
|
return buy.compareTo(order.buy);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
|
||||||
|
Order order = (Order) o;
|
||||||
|
|
||||||
|
return Double.compare(order.profit, profit) == 0 && buy.equals(order.buy) && sell.equals(order.sell);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int result;
|
||||||
|
long temp;
|
||||||
|
result = sell.hashCode();
|
||||||
|
result = 31 * result + buy.hashCode();
|
||||||
|
temp = Double.doubleToLongBits(profit);
|
||||||
|
result = 31 * result + (int) (temp ^ (temp >>> 32));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
final StringBuilder sb = new StringBuilder("Order{");
|
||||||
|
sb.append("sell=").append(sell);
|
||||||
|
sb.append(", buy=").append(buy);
|
||||||
|
sb.append(", profit=").append(profit);
|
||||||
|
sb.append('}');
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -33,6 +33,7 @@ public abstract class Vendor implements Comparable<Vendor> {
|
|||||||
List<Offer> offers = getOffers()
|
List<Offer> offers = getOffers()
|
||||||
.stream()
|
.stream()
|
||||||
.filter(offer -> offer.hasType(offerType))
|
.filter(offer -> offer.hasType(offerType))
|
||||||
|
.sorted()
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
return Collections.unmodifiableCollection(offers);
|
return Collections.unmodifiableCollection(offers);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user