diff --git a/client/src/main/java/ru/trader/controllers/OrdersController.java b/client/src/main/java/ru/trader/controllers/OrdersController.java index 14b64d8..65b9e4a 100644 --- a/client/src/main/java/ru/trader/controllers/OrdersController.java +++ b/client/src/main/java/ru/trader/controllers/OrdersController.java @@ -19,7 +19,6 @@ import ru.trader.view.support.Localization; import java.util.Collection; import java.util.List; -import java.util.stream.Collectors; import static java.util.stream.Collectors.toList; @@ -39,7 +38,7 @@ public class OrdersController { private TableColumn maxCount; @FXML - private TableColumn curProfit; + private TableColumn curProfit; @FXML private TableColumn curDistance; @@ -56,7 +55,7 @@ public class OrdersController { tblBuyers.getSelectionModel().selectedItemProperty().addListener((v, o, n) -> setBuyer(n)); curProfit.setCellValueFactory(param -> { OfferModel offer = param.getValue(); - return order !=null ? order.getProfit(offer) : new SimpleDoubleProperty(Double.NaN).asObject(); + return order !=null ? order.getProfit(offer) : new SimpleDoubleProperty(Double.NaN); }); curDistance.setCellValueFactory(param -> { OfferModel offer = param.getValue(); diff --git a/client/src/main/java/ru/trader/model/OrderModel.java b/client/src/main/java/ru/trader/model/OrderModel.java index df97e42..6c9078e 100644 --- a/client/src/main/java/ru/trader/model/OrderModel.java +++ b/client/src/main/java/ru/trader/model/OrderModel.java @@ -3,6 +3,7 @@ package ru.trader.model; import javafx.beans.binding.Bindings; import javafx.beans.property.*; import javafx.beans.value.ObservableValue; +import ru.trader.core.Order; import ru.trader.graph.PathRoute; import ru.trader.model.support.ModelBindings; @@ -45,7 +46,7 @@ public class OrderModel { public OrderModel(OfferModel offer, double balance, long limit) { this(offer); - this.max.setValue(Math.min(offer.getCount(), Math.min(limit, (long) Math.floor(balance / offer.getPrice())))); + this.max.setValue(Order.getMaxCount(offer.getOffer(), balance, limit)); } PathRoute getPath() { @@ -131,8 +132,9 @@ public class OrderModel { return profitProperty().get(); } - public ObservableValue getProfit(OfferModel buyer) { - return buyer.priceProperty().subtract(offer.priceProperty()).multiply(Bindings.min(max, buyer.countProperty())).asObject(); + public ObservableValue getProfit(OfferModel buyer) { + return Bindings.createDoubleBinding(() -> offer.getPrice() * Order.getMaxCount(offer.getOffer(), buyer.getOffer(), max.get()), + buyer.priceProperty(), offer.priceProperty(), max, buyer.countProperty()); } public ReadOnlyDoubleProperty profitProperty() { diff --git a/core/src/main/java/ru/trader/core/MarketAnalyzer.java b/core/src/main/java/ru/trader/core/MarketAnalyzer.java index 0fe3526..eed30cd 100644 --- a/core/src/main/java/ru/trader/core/MarketAnalyzer.java +++ b/core/src/main/java/ru/trader/core/MarketAnalyzer.java @@ -49,7 +49,7 @@ public class MarketAnalyzer { for (Offer sell : vendor.getAllSellOffers()) { LOG.trace("Sell offer {}", sell); if (sell.getCount() == 0) continue; - long count = Math.min(sell.getCount(), Math.min(cargo, (long) Math.floor(balance / sell.getPrice()))); + long count = Order.getMaxCount(sell, balance, cargo); LOG.trace("count = {}", count); if (count == 0) continue; Iterator buyers = market.getStatBuy(sell.getItem()).getOffers().descendingIterator(); @@ -84,7 +84,7 @@ public class MarketAnalyzer { for (Vendor seller : from.get()) { for (Offer sell : seller.getAllSellOffers()) { if (sell.getCount() == 0) continue; - long count = Math.min(sell.getCount(), Math.min(cargo, (long) Math.floor(balance / sell.getPrice()))); + long count = Order.getMaxCount(sell, balance, cargo); LOG.trace("Sell offer {}, count = {}", sell, count); if (count == 0) continue; for (Vendor buyer : to.get()) { @@ -109,7 +109,7 @@ public class MarketAnalyzer { } for (Offer sell : from.getAllSellOffers()) { if (sell.getCount() == 0) continue; - long count = Math.min(sell.getCount(), Math.min(cargo, (long) Math.floor(balance / sell.getPrice()))); + long count = Order.getMaxCount(sell, balance, cargo); LOG.trace("Sell offer {}, count = {}", sell, count); if (count == 0) continue; diff --git a/core/src/main/java/ru/trader/core/Order.java b/core/src/main/java/ru/trader/core/Order.java index 8a5a85d..50ccbb8 100644 --- a/core/src/main/java/ru/trader/core/Order.java +++ b/core/src/main/java/ru/trader/core/Order.java @@ -19,7 +19,7 @@ public class Order implements Comparable { public Order(Offer sell, Offer buy, long count) { this.sell = sell; this.buy = buy; - this.count = Math.min(Math.min(buy.getCount(), sell.getCount()), count); + this.count = getMaxCount(sell, buy, count); this.profit = (buy.getPrice() - sell.getPrice()) * count; } @@ -32,7 +32,7 @@ public class Order implements Comparable { } public void setCount(long count){ - this.count = Math.min(Math.min(buy.getCount(), sell.getCount()), count); + this.count = getMaxCount(sell, buy, count); this.profit = (buy.getPrice() - sell.getPrice()) * count; } @@ -110,6 +110,24 @@ public class Order implements Comparable { } public void setMax(double balance, long limit) { - setCount((long) Math.min(balance/sell.getPrice(), limit)); + setCount(getMaxCount(sell, balance, limit)); + } + + public static long getMaxCount(Offer sell, double balance, long limit){ + return getMaxCount(sell, null, balance, limit); + } + + public static long getMaxCount(Offer sell, Offer buy, long limit){ + return getMaxCount(sell, buy, Double.POSITIVE_INFINITY, limit); + } + + public static long getMaxCount(Offer sell, Offer buy, double balance, long limit){ + long supply = sell.getCount(); + if (supply == 0) return 0; + if (supply == -1) supply = Long.MAX_VALUE; + long demand = buy != null ? buy.getCount() : -1; + if (demand <= 0) demand = Long.MAX_VALUE; + if (Double.isInfinite(balance)) return Math.min(limit, Math.min(supply, demand)); + return (long) Math.min(limit, Math.min(Math.min(supply, demand), Math.floor(balance/sell.getPrice()))); } } diff --git a/core/src/test/java/ru/trader/graph/PathRouteTest.java b/core/src/test/java/ru/trader/graph/PathRouteTest.java index cd6d5e2..fadbd8d 100644 --- a/core/src/test/java/ru/trader/graph/PathRouteTest.java +++ b/core/src/test/java/ru/trader/graph/PathRouteTest.java @@ -29,12 +29,12 @@ public class PathRouteTest extends Assert { v1 = new SimpleVendor("v1",0,0,0); v2 = new SimpleVendor("v2",0,0,0); - v1.add(new SimpleOffer(OFFER_TYPE.SELL, ITEM1, 100, 1)); - v1.add(new SimpleOffer(OFFER_TYPE.SELL, ITEM2, 200, 1)); - v1.add(new SimpleOffer(OFFER_TYPE.SELL, ITEM3, 300, 1)); - v2.add(new SimpleOffer(OFFER_TYPE.BUY, ITEM1, 300, 1)); - v2.add(new SimpleOffer(OFFER_TYPE.BUY, ITEM2, 350, 1)); - v2.add(new SimpleOffer(OFFER_TYPE.BUY, ITEM3, 400, 1)); + v1.add(new SimpleOffer(OFFER_TYPE.SELL, ITEM1, 100, -1)); + v1.add(new SimpleOffer(OFFER_TYPE.SELL, ITEM2, 200, -1)); + v1.add(new SimpleOffer(OFFER_TYPE.SELL, ITEM3, 300, -1)); + v2.add(new SimpleOffer(OFFER_TYPE.BUY, ITEM1, 300, -1)); + v2.add(new SimpleOffer(OFFER_TYPE.BUY, ITEM2, 350, -1)); + v2.add(new SimpleOffer(OFFER_TYPE.BUY, ITEM3, 400, -1)); PathRoute res = new PathRoute(new Vertex<>(v1.getPlace())); res = (PathRoute) res.connectTo(new Vertex<>(v2.getPlace()), false); @@ -70,12 +70,12 @@ public class PathRouteTest extends Assert { v2 = new SimpleVendor("v2",0,0,0); v3 = new SimpleVendor("v3",0,0,0); - v1.add(new SimpleOffer(OFFER_TYPE.SELL, ITEM1, 100, 1)); - v1.add(new SimpleOffer(OFFER_TYPE.SELL, ITEM3, 300, 1)); - v2.add(new SimpleOffer(OFFER_TYPE.SELL, ITEM2, 200, 1)); - v3.add(new SimpleOffer(OFFER_TYPE.BUY, ITEM1, 300, 1)); - v3.add(new SimpleOffer(OFFER_TYPE.BUY, ITEM2, 350, 1)); - v3.add(new SimpleOffer(OFFER_TYPE.BUY, ITEM3, 400, 1)); + v1.add(new SimpleOffer(OFFER_TYPE.SELL, ITEM1, 100, -1)); + v1.add(new SimpleOffer(OFFER_TYPE.SELL, ITEM3, 300, -1)); + v2.add(new SimpleOffer(OFFER_TYPE.SELL, ITEM2, 200, -1)); + v3.add(new SimpleOffer(OFFER_TYPE.BUY, ITEM1, 300, -1)); + v3.add(new SimpleOffer(OFFER_TYPE.BUY, ITEM2, 350, -1)); + v3.add(new SimpleOffer(OFFER_TYPE.BUY, ITEM3, 400, -1)); PathRoute res = new PathRoute(new Vertex<>(v1.getPlace())); res = (PathRoute) res.connectTo(new Vertex<>(v2.getPlace()), false); @@ -118,16 +118,16 @@ public class PathRouteTest extends Assert { v3 = new SimpleVendor("v3",0,0,0); v4 = new SimpleVendor("v4",0,0,0); - v1.add(new SimpleOffer(OFFER_TYPE.SELL, ITEM1, 100, 1)); - v1.add(new SimpleOffer(OFFER_TYPE.SELL, ITEM2, 200, 1)); - v1.add(new SimpleOffer(OFFER_TYPE.SELL, ITEM3, 300, 1)); - v2.add(new SimpleOffer(OFFER_TYPE.SELL, ITEM1, 150, 1)); - v2.add(new SimpleOffer(OFFER_TYPE.SELL, ITEM3, 320, 1)); - v3.add(new SimpleOffer(OFFER_TYPE.SELL, ITEM3, 390, 1)); + v1.add(new SimpleOffer(OFFER_TYPE.SELL, ITEM1, 100, -1)); + v1.add(new SimpleOffer(OFFER_TYPE.SELL, ITEM2, 200, -1)); + v1.add(new SimpleOffer(OFFER_TYPE.SELL, ITEM3, 300, -1)); + v2.add(new SimpleOffer(OFFER_TYPE.SELL, ITEM1, 150, -1)); + v2.add(new SimpleOffer(OFFER_TYPE.SELL, ITEM3, 320, -1)); + v3.add(new SimpleOffer(OFFER_TYPE.SELL, ITEM3, 390, -1)); - v2.add(new SimpleOffer(OFFER_TYPE.BUY, ITEM2, 225, 1)); - v3.add(new SimpleOffer(OFFER_TYPE.BUY, ITEM1, 200, 1)); - v4.add(new SimpleOffer(OFFER_TYPE.BUY, ITEM3, 450, 1)); + v2.add(new SimpleOffer(OFFER_TYPE.BUY, ITEM2, 225, -1)); + v3.add(new SimpleOffer(OFFER_TYPE.BUY, ITEM1, 200, -1)); + v4.add(new SimpleOffer(OFFER_TYPE.BUY, ITEM3, 450, -1)); PathRoute res = new PathRoute(new Vertex<>(v1.getPlace())); res = (PathRoute) res.connectTo(new Vertex<>(v2.getPlace()), false); @@ -182,16 +182,16 @@ public class PathRouteTest extends Assert { v4 = new SimpleVendor("v4",0,0,0); v5 = new SimpleVendor("v5",0,0,0); - v1.add(new SimpleOffer(OFFER_TYPE.SELL, ITEM1, 410, 1)); - v1.add(new SimpleOffer(OFFER_TYPE.SELL, ITEM2, 200, 1)); - v1.add(new SimpleOffer(OFFER_TYPE.SELL, ITEM3, 300, 1)); - v2.add(new SimpleOffer(OFFER_TYPE.SELL, ITEM2, 270, 1)); - v4.add(new SimpleOffer(OFFER_TYPE.SELL, ITEM1, 300, 1)); + v1.add(new SimpleOffer(OFFER_TYPE.SELL, ITEM1, 410, -1)); + v1.add(new SimpleOffer(OFFER_TYPE.SELL, ITEM2, 200, -1)); + v1.add(new SimpleOffer(OFFER_TYPE.SELL, ITEM3, 300, -1)); + v2.add(new SimpleOffer(OFFER_TYPE.SELL, ITEM2, 270, -1)); + v4.add(new SimpleOffer(OFFER_TYPE.SELL, ITEM1, 300, -1)); - v2.add(new SimpleOffer(OFFER_TYPE.BUY, ITEM1, 470, 1)); - v3.add(new SimpleOffer(OFFER_TYPE.BUY, ITEM2, 300, 1)); - v4.add(new SimpleOffer(OFFER_TYPE.BUY, ITEM3, 370, 1)); - v5.add(new SimpleOffer(OFFER_TYPE.BUY, ITEM1, 400, 1)); + v2.add(new SimpleOffer(OFFER_TYPE.BUY, ITEM1, 470, -1)); + v3.add(new SimpleOffer(OFFER_TYPE.BUY, ITEM2, 300, -1)); + v4.add(new SimpleOffer(OFFER_TYPE.BUY, ITEM3, 370, -1)); + v5.add(new SimpleOffer(OFFER_TYPE.BUY, ITEM1, 400, -1)); PathRoute res = new PathRoute(new Vertex<>(v1.getPlace())); res = (PathRoute) res.connectTo(new Vertex<>(v2.getPlace()), false); @@ -254,16 +254,16 @@ public class PathRouteTest extends Assert { v3 = new SimpleVendor("v3",0,0,0); v4 = new SimpleVendor("v4",0,0,0); - v1.add(new SimpleOffer(OFFER_TYPE.SELL, ITEM1, 100, 1)); - v1.add(new SimpleOffer(OFFER_TYPE.SELL, ITEM2, 200, 1)); - v1.add(new SimpleOffer(OFFER_TYPE.SELL, ITEM3, 300, 1)); - v2.add(new SimpleOffer(OFFER_TYPE.SELL, ITEM1, 150, 1)); - v2.add(new SimpleOffer(OFFER_TYPE.SELL, ITEM3, 320, 1)); - v3.add(new SimpleOffer(OFFER_TYPE.SELL, ITEM3, 390, 1)); + v1.add(new SimpleOffer(OFFER_TYPE.SELL, ITEM1, 100, -1)); + v1.add(new SimpleOffer(OFFER_TYPE.SELL, ITEM2, 200, -1)); + v1.add(new SimpleOffer(OFFER_TYPE.SELL, ITEM3, 300, -1)); + v2.add(new SimpleOffer(OFFER_TYPE.SELL, ITEM1, 150, -1)); + v2.add(new SimpleOffer(OFFER_TYPE.SELL, ITEM3, 320, -1)); + v3.add(new SimpleOffer(OFFER_TYPE.SELL, ITEM3, 390, -1)); - v2.add(new SimpleOffer(OFFER_TYPE.BUY, ITEM2, 225, 1)); - v3.add(new SimpleOffer(OFFER_TYPE.BUY, ITEM1, 200, 1)); - v4.add(new SimpleOffer(OFFER_TYPE.BUY, ITEM3, 450, 1)); + v2.add(new SimpleOffer(OFFER_TYPE.BUY, ITEM2, 225, -1)); + v3.add(new SimpleOffer(OFFER_TYPE.BUY, ITEM1, 200, -1)); + v4.add(new SimpleOffer(OFFER_TYPE.BUY, ITEM3, 450, -1)); PathRoute res = new PathRoute(new Vertex<>(v1.getPlace())); res = (PathRoute) res.connectTo(new Vertex<>(v2.getPlace()), false); @@ -317,13 +317,13 @@ public class PathRouteTest extends Assert { v1 = new SimpleVendor("v1",0,0,0); v2 = new SimpleVendor("v2",0,0,0); - v1.add(new SimpleOffer(OFFER_TYPE.SELL, ITEM1, 100, 1)); - v1.add(new SimpleOffer(OFFER_TYPE.SELL, ITEM2, 200, 1)); - v1.add(new SimpleOffer(OFFER_TYPE.SELL, ITEM3, 300, 1)); - v2.add(new SimpleOffer(OFFER_TYPE.SELL, ITEM1, 150, 1)); - v2.add(new SimpleOffer(OFFER_TYPE.SELL, ITEM3, 320, 1)); + v1.add(new SimpleOffer(OFFER_TYPE.SELL, ITEM1, 100, -1)); + v1.add(new SimpleOffer(OFFER_TYPE.SELL, ITEM2, 200, -1)); + v1.add(new SimpleOffer(OFFER_TYPE.SELL, ITEM3, 300, -1)); + v2.add(new SimpleOffer(OFFER_TYPE.SELL, ITEM1, 150, -1)); + v2.add(new SimpleOffer(OFFER_TYPE.SELL, ITEM3, 320, -1)); - v2.add(new SimpleOffer(OFFER_TYPE.BUY, ITEM2, 225, 1)); + v2.add(new SimpleOffer(OFFER_TYPE.BUY, ITEM2, 225, -1)); PathRoute res = new PathRoute(new Vertex<>(v1.getPlace())); res = (PathRoute) res.connectTo(new Vertex<>(v2.getPlace()), false); @@ -337,10 +337,10 @@ public class PathRouteTest extends Assert { v3 = new SimpleVendor("v3",0,0,0); v4 = new SimpleVendor("v4",0,0,0); - v3.add(new SimpleOffer(OFFER_TYPE.SELL, ITEM3, 390, 1)); + v3.add(new SimpleOffer(OFFER_TYPE.SELL, ITEM3, 390, -1)); - v3.add(new SimpleOffer(OFFER_TYPE.BUY, ITEM1, 200, 1)); - v4.add(new SimpleOffer(OFFER_TYPE.BUY, ITEM3, 450, 1)); + v3.add(new SimpleOffer(OFFER_TYPE.BUY, ITEM1, 200, -1)); + v4.add(new SimpleOffer(OFFER_TYPE.BUY, ITEM3, 450, -1)); PathRoute res = new PathRoute(new Vertex<>(v2.getPlace())); res = (PathRoute) res.connectTo(new Vertex<>(v3.getPlace()), false); diff --git a/core/src/test/java/ru/trader/graph/RouteGraphTest.java b/core/src/test/java/ru/trader/graph/RouteGraphTest.java index 1036030..55e3cda 100644 --- a/core/src/test/java/ru/trader/graph/RouteGraphTest.java +++ b/core/src/test/java/ru/trader/graph/RouteGraphTest.java @@ -36,16 +36,16 @@ public class RouteGraphTest extends Assert { v3 = new SimpleVendor("v3"); v4 = new SimpleVendor("v4"); - v1.add(new SimpleOffer(OFFER_TYPE.SELL, ITEM1, 100, 1)); - v1.add(new SimpleOffer(OFFER_TYPE.SELL, ITEM2, 200, 1)); - v1.add(new SimpleOffer(OFFER_TYPE.SELL, ITEM3, 300, 1)); - v2.add(new SimpleOffer(OFFER_TYPE.SELL, ITEM1, 150, 1)); - v2.add(new SimpleOffer(OFFER_TYPE.SELL, ITEM3, 320, 1)); - v3.add(new SimpleOffer(OFFER_TYPE.SELL, ITEM3, 390, 1)); + v1.add(new SimpleOffer(OFFER_TYPE.SELL, ITEM1, 100, -1)); + v1.add(new SimpleOffer(OFFER_TYPE.SELL, ITEM2, 200, -1)); + v1.add(new SimpleOffer(OFFER_TYPE.SELL, ITEM3, 300, -1)); + v2.add(new SimpleOffer(OFFER_TYPE.SELL, ITEM1, 150, -1)); + v2.add(new SimpleOffer(OFFER_TYPE.SELL, ITEM3, 320, -1)); + v3.add(new SimpleOffer(OFFER_TYPE.SELL, ITEM3, 390, -1)); - v2.add(new SimpleOffer(OFFER_TYPE.BUY, ITEM2, 225, 1)); - v3.add(new SimpleOffer(OFFER_TYPE.BUY, ITEM1, 200, 1)); - v4.add(new SimpleOffer(OFFER_TYPE.BUY, ITEM3, 450, 1)); + v2.add(new SimpleOffer(OFFER_TYPE.BUY, ITEM2, 225, -1)); + v3.add(new SimpleOffer(OFFER_TYPE.BUY, ITEM1, 200, -1)); + v4.add(new SimpleOffer(OFFER_TYPE.BUY, ITEM3, 450, -1)); p1.add(v1);p2.add(v2);p3.add(v3);p4.add(v4); market.add(p1);market.add(p2);market.add(p3);market.add(p4);