implement auto update from EMDN
This commit is contained in:
137
client/src/main/java/ru/trader/EMDNUpdater.java
Normal file
137
client/src/main/java/ru/trader/EMDNUpdater.java
Normal file
@@ -0,0 +1,137 @@
|
||||
package ru.trader;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import ru.trader.controllers.MainController;
|
||||
import ru.trader.emdn.EMDN;
|
||||
import ru.trader.emdn.ItemData;
|
||||
import ru.trader.emdn.Station;
|
||||
import ru.trader.model.MarketModel;
|
||||
import ru.trader.model.support.VendorUpdater;
|
||||
|
||||
import java.util.concurrent.*;
|
||||
|
||||
public class EMDNUpdater {
|
||||
private final static Logger LOG = LoggerFactory.getLogger(EMDNUpdater.class);
|
||||
private final static EMDN emdn = new EMDN();
|
||||
private static ScheduledExecutorService executor;
|
||||
private static ScheduledFuture<?> autoupdate;
|
||||
private static MarketModel market;
|
||||
private static EMDNUpdate emdnUpdater;
|
||||
private static long interval;
|
||||
|
||||
public static void updateFromEMDN(VendorUpdater updater){
|
||||
Station emdnData = emdn.getVendor(updater.getName());
|
||||
LOG.debug("Update {} from EMDN", updater.getName());
|
||||
if (emdnData == null){
|
||||
LOG.trace("Not found in EMDN");
|
||||
return;
|
||||
}
|
||||
for (VendorUpdater.FakeOffer offer : updater.getOffers()) {
|
||||
if (offer.getItem().isMarketItem()){
|
||||
ItemData data = emdnData.getData(offer.getItem().getId());
|
||||
LOG.debug("Update item {} to {}", offer.getItem().getName(), data);
|
||||
if (data != null){
|
||||
offer.setSprice(data.getBuy());
|
||||
offer.setBprice(data.getSell());
|
||||
} else {
|
||||
offer.setSprice(0);
|
||||
offer.setBprice(0);
|
||||
}
|
||||
} else {
|
||||
LOG.trace("Is not market item, skip");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void init(){
|
||||
setMarket(MainController.getMarket());
|
||||
setSub(Main.SETTINGS.getEMDNSub());
|
||||
setActivate(Main.SETTINGS.getEMDNActive());
|
||||
setUpdateOnly(Main.SETTINGS.getEMDNUpdateOnly());
|
||||
if (emdn.isActive())
|
||||
setInterval(Main.SETTINGS.getEMDNAutoUpdate());
|
||||
}
|
||||
|
||||
public static void shutdown(){
|
||||
if (executor != null) {
|
||||
LOG.debug("Shutdown auto update");
|
||||
autoupdate.cancel(true);
|
||||
executor.shutdown();
|
||||
}
|
||||
emdn.shutdown();
|
||||
}
|
||||
|
||||
public static void setMarket(MarketModel market) {
|
||||
EMDNUpdater.market = market;
|
||||
EMDNUpdate old = emdnUpdater;
|
||||
emdnUpdater = new EMDNUpdate();
|
||||
if (old != null){
|
||||
setUpdateOnly(old.updater.isUpdateOnly());
|
||||
}
|
||||
if (executor != null){
|
||||
setInterval(interval);
|
||||
}
|
||||
}
|
||||
|
||||
public static void setSub(String subServer){
|
||||
emdn.connectTo(subServer);
|
||||
}
|
||||
|
||||
public static void setActivate(boolean activate){
|
||||
if (activate) {
|
||||
emdn.start();
|
||||
}
|
||||
else {
|
||||
emdn.shutdown();
|
||||
setInterval(0);
|
||||
}
|
||||
}
|
||||
|
||||
public static void setUpdateOnly(boolean updateOnly) {
|
||||
emdnUpdater.updater.setUpdateOnly(updateOnly);
|
||||
}
|
||||
|
||||
public static void setInterval(long interval) {
|
||||
if (emdn.isActive()){
|
||||
if (interval > 0) {
|
||||
if (executor != null){
|
||||
LOG.debug("Cancel previous auto update");
|
||||
autoupdate.cancel(true);
|
||||
}
|
||||
if (executor == null) executor = Executors.newSingleThreadScheduledExecutor();
|
||||
LOG.debug("Start auto update each {} sec", interval);
|
||||
autoupdate = executor.scheduleAtFixedRate(emdnUpdater, interval, interval, TimeUnit.SECONDS);
|
||||
} else {
|
||||
if (executor != null){
|
||||
LOG.debug("Stop auto update");
|
||||
autoupdate.cancel(true);
|
||||
executor.shutdown();
|
||||
executor = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
EMDNUpdater.interval = interval;
|
||||
}
|
||||
|
||||
private static class EMDNUpdate implements Runnable {
|
||||
private final VendorUpdater updater;
|
||||
|
||||
private EMDNUpdate() {
|
||||
updater = new VendorUpdater(market);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
market.vendorsProperty().get().forEach((vendor) -> {
|
||||
LOG.trace("Auto update {}", vendor);
|
||||
updater.reset();
|
||||
updater.init(vendor);
|
||||
updateFromEMDN(updater);
|
||||
updater.commit();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -29,10 +29,10 @@ public class Main extends Application {
|
||||
public void start(Stage primaryStage) throws Exception {
|
||||
SETTINGS = new Settings(new File("profile.properties"));
|
||||
SETTINGS.load();
|
||||
World.start();
|
||||
Main.primaryStage = primaryStage;
|
||||
loadMainScene();
|
||||
loadResources();
|
||||
EMDNUpdater.init();
|
||||
primaryStage.show();
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ public class Main extends Application {
|
||||
if (res == Dialog.Actions.YES) World.save();
|
||||
else if (res == Dialog.Actions.CANCEL) we.consume();
|
||||
}
|
||||
World.shutdown();
|
||||
EMDNUpdater.shutdown();
|
||||
SETTINGS.save();
|
||||
Screeners.closeAll();
|
||||
} catch (FileNotFoundException | UnsupportedEncodingException | XMLStreamException e) {
|
||||
|
||||
@@ -19,7 +19,6 @@ import java.io.UnsupportedEncodingException;
|
||||
public class World {
|
||||
private static Market world;
|
||||
private static final String STORE_FILE="world.xml";
|
||||
private final static EMDN emdn = new EMDN();
|
||||
|
||||
static {
|
||||
try {
|
||||
@@ -46,28 +45,4 @@ public class World {
|
||||
public static Market getMarket() {
|
||||
return world;
|
||||
}
|
||||
|
||||
public static Station getEMDN(String name){
|
||||
return emdn.getVendor(name);
|
||||
}
|
||||
|
||||
private static void initEmdn(){
|
||||
emdn.connectTo(Main.SETTINGS.getEMDNSub());
|
||||
if (Main.SETTINGS.getEMDNActive()){
|
||||
emdn.start();
|
||||
}
|
||||
}
|
||||
|
||||
public static EMDN getEmdn(){
|
||||
return emdn;
|
||||
}
|
||||
|
||||
public static void start(){
|
||||
initEmdn();
|
||||
}
|
||||
|
||||
public static void shutdown(){
|
||||
emdn.shutdown();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import org.controlsfx.control.action.Action;
|
||||
import org.controlsfx.dialog.Dialog;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import ru.trader.EMDNUpdater;
|
||||
import ru.trader.Main;
|
||||
import ru.trader.World;
|
||||
import ru.trader.emdn.EMDN;
|
||||
@@ -30,14 +31,6 @@ public class SettingsController {
|
||||
@FXML
|
||||
private NumberField emdnUpdateTime;
|
||||
|
||||
@FXML
|
||||
private void initialize(){
|
||||
emdnOn.setSelected(Main.SETTINGS.getEMDNActive());
|
||||
emdnSubServ.setText(Main.SETTINGS.getEMDNSub());
|
||||
emdnUpdateOnly.setSelected(Main.SETTINGS.getEMDNUpdateOnly());
|
||||
emdnUpdateTime.setValue(Main.SETTINGS.getEMDNAutoUpdate());
|
||||
}
|
||||
|
||||
private final Action actSave = new AbstractAction(Localization.getString("dialog.button.save")) {
|
||||
{
|
||||
ButtonBar.setType(this, ButtonBar.ButtonType.OK_DONE);
|
||||
@@ -51,21 +44,31 @@ public class SettingsController {
|
||||
}
|
||||
};
|
||||
|
||||
private void save() {
|
||||
Main.SETTINGS.setEMDNActive(emdnOn.isSelected());
|
||||
Main.SETTINGS.setEMDNSub(emdnSubServ.getText());
|
||||
Main.SETTINGS.setEMDNUpdateOnly(emdnUpdateOnly.isSelected());
|
||||
Main.SETTINGS.setEMDNAutoUpdate(emdnUpdateTime.getValue().longValue());
|
||||
EMDN emdn = World.getEmdn();
|
||||
emdn.connectTo(emdnSubServ.getText());
|
||||
if (emdnOn.isSelected()){
|
||||
emdn.start();
|
||||
} else {
|
||||
emdn.shutdown();
|
||||
@FXML
|
||||
private void initialize(){
|
||||
init();
|
||||
}
|
||||
|
||||
private void init(){
|
||||
emdnSubServ.setText(Main.SETTINGS.getEMDNSub());
|
||||
emdnOn.setSelected(Main.SETTINGS.getEMDNActive());
|
||||
emdnUpdateOnly.setSelected(Main.SETTINGS.getEMDNUpdateOnly());
|
||||
emdnUpdateTime.setValue(Main.SETTINGS.getEMDNAutoUpdate());
|
||||
}
|
||||
|
||||
private void save() {
|
||||
Main.SETTINGS.setEMDNSub(emdnSubServ.getText());
|
||||
EMDNUpdater.setSub(emdnSubServ.getText());
|
||||
Main.SETTINGS.setEMDNActive(emdnOn.isSelected());
|
||||
EMDNUpdater.setActivate(emdnOn.isSelected());
|
||||
Main.SETTINGS.setEMDNUpdateOnly(emdnUpdateOnly.isSelected());
|
||||
EMDNUpdater.setUpdateOnly(emdnUpdateOnly.isSelected());
|
||||
Main.SETTINGS.setEMDNAutoUpdate(emdnUpdateTime.getValue().longValue());
|
||||
EMDNUpdater.setInterval(emdnUpdateTime.getValue().longValue());
|
||||
}
|
||||
|
||||
public Action showDialog(Parent parent, Parent content){
|
||||
init();
|
||||
Dialog dlg = new Dialog(parent, Localization.getString("settings.title"));
|
||||
dlg.setContent(content);
|
||||
dlg.getActions().addAll(actSave, Dialog.Actions.CANCEL);
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
package ru.trader.controllers;
|
||||
|
||||
import javafx.beans.property.DoubleProperty;
|
||||
import javafx.beans.property.ReadOnlyStringProperty;
|
||||
import javafx.beans.property.SimpleDoubleProperty;
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.Parent;
|
||||
@@ -16,12 +13,11 @@ import org.controlsfx.dialog.DefaultDialogAction;
|
||||
import org.controlsfx.dialog.Dialog;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import ru.trader.World;
|
||||
import ru.trader.core.OFFER_TYPE;
|
||||
import ru.trader.EMDNUpdater;
|
||||
import ru.trader.emdn.ItemData;
|
||||
import ru.trader.emdn.Station;
|
||||
import ru.trader.model.*;
|
||||
import ru.trader.model.support.BindingsHelper;
|
||||
import ru.trader.model.support.VendorUpdater;
|
||||
import ru.trader.view.support.Localization;
|
||||
import ru.trader.view.support.NumberField;
|
||||
import ru.trader.view.support.PriceStringConverter;
|
||||
@@ -34,8 +30,6 @@ import java.util.Optional;
|
||||
public class VendorEditorController {
|
||||
private final static Logger LOG = LoggerFactory.getLogger(VendorEditorController.class);
|
||||
|
||||
private VendorModel vendor;
|
||||
|
||||
private final Action actSave = new AbstractAction(Localization.getString("dialog.button.save")) {
|
||||
{
|
||||
ButtonBar.setType(this, ButtonBar.ButtonType.OK_DONE);
|
||||
@@ -45,7 +39,8 @@ public class VendorEditorController {
|
||||
public void handle(ActionEvent event) {
|
||||
Dialog dlg = (Dialog) event.getSource();
|
||||
items.getSelectionModel().selectFirst();
|
||||
saveChanges();
|
||||
updater.commit();
|
||||
items.getSelectionModel().clearSelection();
|
||||
dlg.hide();
|
||||
}
|
||||
};
|
||||
@@ -58,6 +53,7 @@ public class VendorEditorController {
|
||||
@Override
|
||||
public void handle(ActionEvent event) {
|
||||
items.getSelectionModel().selectFirst();
|
||||
items.getSelectionModel().clearSelection();
|
||||
super.handle(event);
|
||||
}
|
||||
};
|
||||
@@ -66,11 +62,11 @@ public class VendorEditorController {
|
||||
private TextField name;
|
||||
|
||||
@FXML
|
||||
private TableView<FakeOffer> items;
|
||||
private TableView<VendorUpdater.FakeOffer> items;
|
||||
@FXML
|
||||
private TableColumn<FakeOffer, Double> buy;
|
||||
private TableColumn<VendorUpdater.FakeOffer, Double> buy;
|
||||
@FXML
|
||||
private TableColumn<FakeOffer, Double> sell;
|
||||
private TableColumn<VendorUpdater.FakeOffer, Double> sell;
|
||||
|
||||
@FXML
|
||||
private NumberField x;
|
||||
@@ -79,6 +75,8 @@ public class VendorEditorController {
|
||||
@FXML
|
||||
private NumberField z;
|
||||
|
||||
private VendorUpdater updater;
|
||||
|
||||
|
||||
@FXML
|
||||
private void initialize() {
|
||||
@@ -86,7 +84,6 @@ public class VendorEditorController {
|
||||
buy.setCellFactory(EditOfferCell.forTable(new PriceStringConverter(), false));
|
||||
sell.setCellFactory(EditOfferCell.forTable(new PriceStringConverter(), true));
|
||||
actSave.disabledProperty().bind(x.wrongProperty().or(y.wrongProperty().or(z.wrongProperty())));
|
||||
fillItems();
|
||||
name.setOnAction((v)->x.requestFocus());
|
||||
x.setOnAction((v) -> z.requestFocus());
|
||||
z.setOnAction((v) -> y.requestFocus());
|
||||
@@ -94,14 +91,21 @@ public class VendorEditorController {
|
||||
items.requestFocus();
|
||||
items.getSelectionModel().select(0, buy);
|
||||
});
|
||||
init();
|
||||
}
|
||||
|
||||
private void init(){
|
||||
updater = new VendorUpdater(MainController.getMarket());
|
||||
name.textProperty().bindBidirectional(updater.nameProperty());
|
||||
x.numberProperty().bindBidirectional(updater.xProperty());
|
||||
y.numberProperty().bindBidirectional(updater.yProperty());
|
||||
z.numberProperty().bindBidirectional(updater.zProperty());
|
||||
items.setItems(updater.getOffers());
|
||||
}
|
||||
|
||||
public Action showDialog(Parent parent, Parent content, VendorModel vendor){
|
||||
this.vendor = vendor;
|
||||
reset();
|
||||
if (vendor != null) {
|
||||
fill();
|
||||
}
|
||||
updater.reset();
|
||||
updater.init(vendor);
|
||||
Dialog dlg = new Dialog(parent, Localization.getString(vendor == null ? "vEditor.title.add" : "vEditor.title.edit"));
|
||||
dlg.setContent(content);
|
||||
dlg.getActions().addAll(actSave, actCancel);
|
||||
@@ -109,50 +113,10 @@ public class VendorEditorController {
|
||||
return dlg.show();
|
||||
}
|
||||
|
||||
|
||||
private void fill(){
|
||||
name.setText(vendor.getName());
|
||||
x.setValue(vendor.getX());
|
||||
y.setValue(vendor.getY());
|
||||
z.setValue(vendor.getZ());
|
||||
vendor.getSells().forEach(this::fillOffer);
|
||||
vendor.getBuys().forEach(this::fillOffer);
|
||||
}
|
||||
|
||||
private void reset(){
|
||||
name.setText("");
|
||||
x.setValue(0);
|
||||
y.setValue(0);
|
||||
z.setValue(0);
|
||||
items.getItems().forEach(FakeOffer::reset);
|
||||
items.getSelectionModel().clearSelection();
|
||||
}
|
||||
|
||||
private void fillItems() {
|
||||
items.setItems(BindingsHelper.observableList(MainController.getMarket().itemsProperty(), (item) -> new FakeOffer(item.getItem())));
|
||||
}
|
||||
|
||||
|
||||
private void fillOffer(OfferModel offer) {
|
||||
for (FakeOffer o : items.getItems()) {
|
||||
if (offer.hasItem(o.item)) {
|
||||
switch (offer.getType()) {
|
||||
case SELL:
|
||||
o.setSell(offer);
|
||||
break;
|
||||
case BUY:
|
||||
o.setBuy(offer);
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void up(){
|
||||
int index = items.getSelectionModel().getSelectedIndex();
|
||||
if (index>0){
|
||||
FakeOffer offer = items.getItems().remove(index);
|
||||
VendorUpdater.FakeOffer offer = items.getItems().remove(index);
|
||||
items.getItems().add(index-1, offer);
|
||||
selectRow(index - 1);
|
||||
}
|
||||
@@ -161,7 +125,7 @@ public class VendorEditorController {
|
||||
public void down(){
|
||||
int index = items.getSelectionModel().getSelectedIndex();
|
||||
if (index>=0 && index<items.getItems().size()-1){
|
||||
FakeOffer offer = items.getItems().remove(index);
|
||||
VendorUpdater.FakeOffer offer = items.getItems().remove(index);
|
||||
items.getItems().add(index+1, offer);
|
||||
selectRow(index + 1);
|
||||
}
|
||||
@@ -172,7 +136,7 @@ public class VendorEditorController {
|
||||
if (item.isPresent()){
|
||||
int index = items.getSelectionModel().getSelectedIndex();
|
||||
if (index<0) index = items.getItems().size()-1;
|
||||
items.getItems().add(index, new FakeOffer(item.get()));
|
||||
updater.add(index, item.get());
|
||||
selectRow(index);
|
||||
}
|
||||
}
|
||||
@@ -183,195 +147,7 @@ public class VendorEditorController {
|
||||
ViewUtils.show(items, index);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void saveChanges(){
|
||||
LOG.info("Save vendor changes");
|
||||
items.getSelectionModel().clearSelection();
|
||||
final MarketModel market = MainController.getMarket();
|
||||
if (vendor == null) {
|
||||
market.setAlert(false);
|
||||
vendor = market.newVendor(name.getText());
|
||||
vendor.setPosition(x.getValue().doubleValue(), y.getValue().doubleValue(), z.getValue().doubleValue());
|
||||
items.getItems().forEach((o) -> commit(market, vendor, o));
|
||||
market.setAlert(true);
|
||||
market.add(vendor);
|
||||
} else {
|
||||
vendor.setName(name.getText());
|
||||
vendor.setPosition(x.getValue().doubleValue(), y.getValue().doubleValue(), z.getValue().doubleValue());
|
||||
items.getItems().forEach((o) -> commit(market, vendor, o));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void commit(MarketModel market, VendorModel vendor, FakeOffer offer){
|
||||
LOG.trace("Commit changes of offers {}", offer);
|
||||
if (offer.isBlank()){
|
||||
LOG.trace("Is blank offer, skip");
|
||||
return;
|
||||
}
|
||||
|
||||
if (offer.isNewBuy()){
|
||||
LOG.trace("Is new buy offer");
|
||||
vendor.add(market.newOffer(OFFER_TYPE.BUY, offer.item, offer.getBprice()));
|
||||
} else if (offer.isRemoveBuy()) {
|
||||
LOG.trace("Is remove buy offer");
|
||||
vendor.remove(offer.buy);
|
||||
} else if (offer.isChangeBuy()){
|
||||
LOG.trace("Is change buy price to {}", offer.getBprice());
|
||||
offer.buy.setPrice(offer.getBprice());
|
||||
} else {
|
||||
LOG.trace("No change buy offer");
|
||||
}
|
||||
|
||||
if (offer.isNewSell()){
|
||||
LOG.trace("Is new sell offer");
|
||||
vendor.add(market.newOffer(OFFER_TYPE.SELL, offer.item, offer.getSprice()));
|
||||
} else if (offer.isRemoveSell()) {
|
||||
LOG.trace("Is remove sell offer");
|
||||
vendor.remove(offer.sell);
|
||||
} else if (offer.isChangeSell()){
|
||||
LOG.trace("Is change sell price to {}", offer.getSprice());
|
||||
offer.sell.setPrice(offer.getSprice());
|
||||
} else {
|
||||
LOG.trace("No change sell offer");
|
||||
}
|
||||
}
|
||||
|
||||
public void updateFromEMDN(){
|
||||
Station emdnData = World.getEMDN(vendor.getName());
|
||||
LOG.debug("Update {} from EMDN", vendor.getName());
|
||||
if (emdnData == null){
|
||||
LOG.trace("Not found in EMDN");
|
||||
return;
|
||||
}
|
||||
for (FakeOffer offer : items.getItems()) {
|
||||
if (offer.item.isMarketItem()){
|
||||
ItemData data = emdnData.getData(offer.item.getId());
|
||||
LOG.debug("Update item {} to {}", offer.item.getName(), data);
|
||||
if (data != null){
|
||||
offer.setSprice(data.getBuy());
|
||||
offer.setBprice(data.getSell());
|
||||
} else {
|
||||
offer.setSprice(0);
|
||||
offer.setBprice(0);
|
||||
}
|
||||
} else {
|
||||
LOG.trace("Is not market item, skip");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class FakeOffer {
|
||||
private final ItemModel item;
|
||||
private DoubleProperty sprice;
|
||||
private DoubleProperty bprice;
|
||||
private OfferModel sell;
|
||||
private OfferModel buy;
|
||||
|
||||
public FakeOffer(ItemModel item){
|
||||
this.item = item;
|
||||
this.sprice = new SimpleDoubleProperty(0);
|
||||
this.bprice = new SimpleDoubleProperty(0);
|
||||
}
|
||||
|
||||
public ReadOnlyStringProperty nameProperty(){
|
||||
return item.nameProperty();
|
||||
}
|
||||
|
||||
public double getSprice() {
|
||||
return sprice.get();
|
||||
}
|
||||
|
||||
public void setSprice(double sprice) {
|
||||
this.sprice.set(sprice);
|
||||
}
|
||||
|
||||
public double getBprice() {
|
||||
return bprice.get();
|
||||
}
|
||||
|
||||
public void setBprice(double bprice) {
|
||||
this.bprice.set(bprice);
|
||||
}
|
||||
|
||||
public DoubleProperty bpriceProperty() {
|
||||
return bprice;
|
||||
}
|
||||
|
||||
public DoubleProperty spriceProperty() {
|
||||
return sprice;
|
||||
}
|
||||
|
||||
public boolean isChangeSell() {
|
||||
return sell!=null && getSprice() != sell.getPrice();
|
||||
}
|
||||
|
||||
public boolean isChangeBuy() {
|
||||
return buy!=null && getBprice() != buy.getPrice();
|
||||
}
|
||||
|
||||
|
||||
public boolean isNewSell() {
|
||||
return sell == null && getSprice() != 0;
|
||||
}
|
||||
|
||||
public boolean isNewBuy() {
|
||||
return buy == null && getBprice() != 0;
|
||||
}
|
||||
|
||||
public boolean isRemoveSell() {
|
||||
return sell != null && getSprice() ==0;
|
||||
}
|
||||
|
||||
public boolean isRemoveBuy() {
|
||||
return buy != null && getBprice() ==0;
|
||||
}
|
||||
|
||||
public boolean isBlank(){
|
||||
return sell == null && getSprice() == 0 && buy == null && getBprice() == 0;
|
||||
}
|
||||
|
||||
public boolean hasItem(ItemModel item){
|
||||
return this.item.equals(item);
|
||||
}
|
||||
|
||||
public double getOldSprice() {
|
||||
return sell != null ? sell.getPrice() : 0;
|
||||
}
|
||||
|
||||
public double getOldBprice() {
|
||||
return buy != null ? buy.getPrice() : 0;
|
||||
}
|
||||
|
||||
public void setSell(OfferModel sell) {
|
||||
this.sell = sell;
|
||||
sprice.set(sell.getPrice());
|
||||
}
|
||||
|
||||
public void setBuy(OfferModel buy) {
|
||||
this.buy = buy;
|
||||
bprice.set(buy.getPrice());
|
||||
}
|
||||
|
||||
public void reset(){
|
||||
this.sell = null;
|
||||
this.buy = null;
|
||||
sprice.setValue(0);
|
||||
bprice.setValue(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "FakeOffer{" +
|
||||
"item=" + item +
|
||||
", sprice=" + sprice.get() +
|
||||
", bprice=" + bprice.get() +
|
||||
", sell=" + sell +
|
||||
", buy=" + buy +
|
||||
'}';
|
||||
}
|
||||
EMDNUpdater.updateFromEMDN(updater);
|
||||
}
|
||||
}
|
||||
|
||||
319
client/src/main/java/ru/trader/model/support/VendorUpdater.java
Normal file
319
client/src/main/java/ru/trader/model/support/VendorUpdater.java
Normal file
@@ -0,0 +1,319 @@
|
||||
package ru.trader.model.support;
|
||||
|
||||
import javafx.beans.property.*;
|
||||
import javafx.collections.ObservableList;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import ru.trader.controllers.MainController;
|
||||
import ru.trader.core.OFFER_TYPE;
|
||||
import ru.trader.model.ItemModel;
|
||||
import ru.trader.model.MarketModel;
|
||||
import ru.trader.model.OfferModel;
|
||||
import ru.trader.model.VendorModel;
|
||||
|
||||
|
||||
public class VendorUpdater {
|
||||
private final static Logger LOG = LoggerFactory.getLogger(VendorUpdater.class);
|
||||
private final ObservableList<FakeOffer> offers;
|
||||
private final StringProperty name;
|
||||
private final DoubleProperty x;
|
||||
private final DoubleProperty y;
|
||||
private final DoubleProperty z;
|
||||
private final MarketModel market;
|
||||
private VendorModel vendor;
|
||||
private boolean updateOnly;
|
||||
|
||||
public VendorUpdater(MarketModel market) {
|
||||
this.market = market;
|
||||
this.offers = BindingsHelper.observableList(MainController.getMarket().itemsProperty(), (item) -> new FakeOffer(item.getItem()));
|
||||
this.name = new SimpleStringProperty();
|
||||
this.x = new SimpleDoubleProperty(0);
|
||||
this.y = new SimpleDoubleProperty(0);
|
||||
this.z = new SimpleDoubleProperty(0);
|
||||
this.updateOnly = false;
|
||||
}
|
||||
|
||||
public void init(VendorModel vendor){
|
||||
LOG.debug("Init update of {}", vendor);
|
||||
this.vendor = vendor;
|
||||
if (vendor != null){
|
||||
name.setValue(vendor.getName());
|
||||
x.setValue(vendor.getX());
|
||||
y.setValue(vendor.getY());
|
||||
z.setValue(vendor.getZ());
|
||||
vendor.getSells().forEach(this::fillOffer);
|
||||
vendor.getBuys().forEach(this::fillOffer);
|
||||
} else {
|
||||
name.setValue("");
|
||||
x.setValue(0);
|
||||
y.setValue(0);
|
||||
z.setValue(0);
|
||||
}
|
||||
}
|
||||
|
||||
private void fillOffer(OfferModel offer) {
|
||||
for (FakeOffer o : offers) {
|
||||
if (offer.hasItem(o.item)) {
|
||||
switch (offer.getType()) {
|
||||
case SELL:
|
||||
o.setSell(offer);
|
||||
break;
|
||||
case BUY:
|
||||
o.setBuy(offer);
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ObservableList<FakeOffer> getOffers() {
|
||||
return offers;
|
||||
}
|
||||
|
||||
public VendorModel getVendor() {
|
||||
return vendor;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name.get();
|
||||
}
|
||||
|
||||
public StringProperty nameProperty() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public double getX() {
|
||||
return x.get();
|
||||
}
|
||||
|
||||
public DoubleProperty xProperty() {
|
||||
return x;
|
||||
}
|
||||
|
||||
public double getY() {
|
||||
return y.get();
|
||||
}
|
||||
|
||||
public DoubleProperty yProperty() {
|
||||
return y;
|
||||
}
|
||||
|
||||
public double getZ() {
|
||||
return z.get();
|
||||
}
|
||||
|
||||
public DoubleProperty zProperty() {
|
||||
return z;
|
||||
}
|
||||
|
||||
public void add(int index, ItemModel item){
|
||||
offers.add(index, new FakeOffer(item));
|
||||
}
|
||||
|
||||
public void commit(){
|
||||
LOG.debug("Save changes of {}", vendor);
|
||||
if (isNew()) {
|
||||
market.setAlert(false);
|
||||
vendor = market.newVendor(name.get());
|
||||
vendor.setPosition(x.get(), y.get(), z.get());
|
||||
offers.forEach(FakeOffer::commit);
|
||||
market.setAlert(true);
|
||||
market.add(vendor);
|
||||
} else {
|
||||
vendor.setName(name.get());
|
||||
vendor.setPosition(x.get(), y.get(), z.get());
|
||||
offers.forEach(FakeOffer::commit);
|
||||
}
|
||||
}
|
||||
|
||||
public void reset(){
|
||||
offers.forEach(FakeOffer::reset);
|
||||
vendor = null;
|
||||
}
|
||||
|
||||
public boolean isNew() {
|
||||
return vendor == null;
|
||||
}
|
||||
|
||||
public void setUpdateOnly(boolean updateOnly) {
|
||||
this.updateOnly = updateOnly;
|
||||
}
|
||||
|
||||
public boolean isUpdateOnly() {
|
||||
return updateOnly;
|
||||
}
|
||||
|
||||
public class FakeOffer {
|
||||
private final ItemModel item;
|
||||
private DoubleProperty sprice;
|
||||
private DoubleProperty bprice;
|
||||
private OfferModel sell;
|
||||
private OfferModel buy;
|
||||
|
||||
public FakeOffer(ItemModel item){
|
||||
this.item = item;
|
||||
this.sprice = new SimpleDoubleProperty(0);
|
||||
this.bprice = new SimpleDoubleProperty(0);
|
||||
}
|
||||
|
||||
public ReadOnlyStringProperty nameProperty(){
|
||||
return item.nameProperty();
|
||||
}
|
||||
|
||||
public double getSprice() {
|
||||
return sprice.get();
|
||||
}
|
||||
|
||||
public void setSprice(double sprice) {
|
||||
this.sprice.set(sprice);
|
||||
}
|
||||
|
||||
public double getBprice() {
|
||||
return bprice.get();
|
||||
}
|
||||
|
||||
public void setBprice(double bprice) {
|
||||
this.bprice.set(bprice);
|
||||
}
|
||||
|
||||
public DoubleProperty bpriceProperty() {
|
||||
return bprice;
|
||||
}
|
||||
|
||||
public DoubleProperty spriceProperty() {
|
||||
return sprice;
|
||||
}
|
||||
|
||||
public boolean isChangeSell() {
|
||||
return sell!=null && getSprice() != sell.getPrice();
|
||||
}
|
||||
|
||||
public boolean isChangeBuy() {
|
||||
return buy!=null && getBprice() != buy.getPrice();
|
||||
}
|
||||
|
||||
|
||||
public boolean isNewSell() {
|
||||
return sell == null && getSprice() != 0;
|
||||
}
|
||||
|
||||
public boolean isNewBuy() {
|
||||
return buy == null && getBprice() != 0;
|
||||
}
|
||||
|
||||
public boolean isRemoveSell() {
|
||||
return sell != null && getSprice() == 0;
|
||||
}
|
||||
|
||||
public boolean isRemoveBuy() {
|
||||
return buy != null && getBprice() == 0;
|
||||
}
|
||||
|
||||
public boolean isBlank(){
|
||||
return sell == null && getSprice() == 0 && buy == null && getBprice() == 0;
|
||||
}
|
||||
|
||||
public boolean hasItem(ItemModel item){
|
||||
return this.item.equals(item);
|
||||
}
|
||||
|
||||
public ItemModel getItem() {
|
||||
return item;
|
||||
}
|
||||
|
||||
public double getOldSprice() {
|
||||
return sell != null ? sell.getPrice() : 0;
|
||||
}
|
||||
|
||||
public double getOldBprice() {
|
||||
return buy != null ? buy.getPrice() : 0;
|
||||
}
|
||||
|
||||
public void setSell(OfferModel sell) {
|
||||
this.sell = sell;
|
||||
sprice.set(sell.getPrice());
|
||||
}
|
||||
|
||||
public void setBuy(OfferModel buy) {
|
||||
this.buy = buy;
|
||||
bprice.set(buy.getPrice());
|
||||
}
|
||||
|
||||
public void reset(){
|
||||
if (sell != null){
|
||||
sell = null;
|
||||
sprice.setValue(Double.NaN);
|
||||
}
|
||||
if (buy != null){
|
||||
buy = null;
|
||||
bprice.setValue(Double.NaN);
|
||||
}
|
||||
sprice.setValue(0);
|
||||
bprice.setValue(0);
|
||||
}
|
||||
|
||||
private void commit(){
|
||||
LOG.trace("Commit changes of offers {}", this);
|
||||
if (isBlank()){
|
||||
LOG.trace("Is blank offer, skip");
|
||||
return;
|
||||
}
|
||||
|
||||
if (isNewBuy()){
|
||||
LOG.trace("Is new buy offer");
|
||||
if (updateOnly) {
|
||||
LOG.trace("Is update only, skip");
|
||||
} else {
|
||||
vendor.add(market.newOffer(OFFER_TYPE.BUY, item, getBprice()));
|
||||
}
|
||||
} else if (isRemoveBuy()) {
|
||||
LOG.trace("Is remove buy offer");
|
||||
if (updateOnly) {
|
||||
LOG.trace("Is update only, skip");
|
||||
} else {
|
||||
vendor.remove(buy);
|
||||
}
|
||||
} else if (isChangeBuy()){
|
||||
LOG.trace("Is change buy price to {}", getBprice());
|
||||
buy.setPrice(getBprice());
|
||||
} else {
|
||||
LOG.trace("No change buy offer");
|
||||
}
|
||||
|
||||
if (isNewSell()){
|
||||
LOG.trace("Is new sell offer");
|
||||
if (updateOnly) {
|
||||
LOG.trace("Is update only, skip");
|
||||
} else {
|
||||
vendor.add(market.newOffer(OFFER_TYPE.SELL, item, getSprice()));
|
||||
}
|
||||
} else if (isRemoveSell()) {
|
||||
LOG.trace("Is remove sell offer");
|
||||
if (updateOnly) {
|
||||
LOG.trace("Is update only, skip");
|
||||
} else {
|
||||
vendor.remove(sell);
|
||||
}
|
||||
} else if (isChangeSell()){
|
||||
LOG.trace("Is change sell price to {}", getSprice());
|
||||
sell.setPrice(getSprice());
|
||||
} else {
|
||||
LOG.trace("No change sell offer");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "FakeOffer{" +
|
||||
"item=" + item +
|
||||
", sprice=" + sprice.get() +
|
||||
", bprice=" + bprice.get() +
|
||||
", sell=" + sell +
|
||||
", buy=" + buy +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,14 +1,9 @@
|
||||
package ru.trader.view.support.cells;
|
||||
|
||||
import javafx.application.Platform;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.control.TableCell;
|
||||
import javafx.scene.control.TableColumn;
|
||||
import javafx.scene.control.TableRow;
|
||||
import javafx.scene.input.MouseEvent;
|
||||
import javafx.scene.layout.Border;
|
||||
import javafx.scene.layout.BorderStroke;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.scene.layout.Priority;
|
||||
import javafx.scene.text.Text;
|
||||
@@ -16,9 +11,9 @@ import javafx.util.Callback;
|
||||
import javafx.util.StringConverter;
|
||||
import org.controlsfx.glyphfont.Glyph;
|
||||
import org.controlsfx.glyphfont.GlyphFontRegistry;
|
||||
import ru.trader.controllers.VendorEditorController;
|
||||
import ru.trader.model.support.VendorUpdater;
|
||||
|
||||
public class EditOfferCell extends TextFieldCell<VendorEditorController.FakeOffer, Double> {
|
||||
public class EditOfferCell extends TextFieldCell<VendorUpdater.FakeOffer, Double> {
|
||||
private final static String CSS_CHANGE = "change";
|
||||
private final static String CSS_ADD = "add";
|
||||
private final static String CSS_REMOVE = "remove";
|
||||
@@ -30,16 +25,16 @@ public class EditOfferCell extends TextFieldCell<VendorEditorController.FakeOffe
|
||||
this.isSell = isSell;
|
||||
}
|
||||
|
||||
public static Callback<TableColumn<VendorEditorController.FakeOffer,Double>, TableCell<VendorEditorController.FakeOffer,Double>> forTable(final StringConverter<Double> converter, boolean isSell) {
|
||||
public static Callback<TableColumn<VendorUpdater.FakeOffer,Double>, TableCell<VendorUpdater.FakeOffer,Double>> forTable(final StringConverter<Double> converter, boolean isSell) {
|
||||
return list -> new EditOfferCell(converter, isSell);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void outItem() {
|
||||
VendorEditorController.FakeOffer offer = (VendorEditorController.FakeOffer) getTableRow().getItem();
|
||||
VendorUpdater.FakeOffer offer = (VendorUpdater.FakeOffer) getTableRow().getItem();
|
||||
double d = isSell? offer.getSprice() - offer.getOldSprice() : offer.getBprice() - offer.getOldBprice();
|
||||
getStyleClass().removeAll(CSS_ADD, CSS_CHANGE, CSS_REMOVE);
|
||||
if (d!=0){
|
||||
if (d !=0 ){
|
||||
HBox hBox = new HBox();
|
||||
hBox.prefWidthProperty().bind(getTableColumn().widthProperty());
|
||||
Text nTxt = new Text(getConverter().toString(isSell ? offer.getSprice() : offer.getBprice()));
|
||||
|
||||
@@ -4,26 +4,27 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentSkipListSet;
|
||||
|
||||
public class ItemStat {
|
||||
private final static Logger LOG = LoggerFactory.getLogger(ItemStat.class);
|
||||
|
||||
private final Item item;
|
||||
private final OFFER_TYPE type;
|
||||
private final TreeSet<Offer> offers;
|
||||
private double sum;
|
||||
private double avg;
|
||||
private final NavigableSet<Offer> offers;
|
||||
private volatile double sum;
|
||||
private volatile double avg;
|
||||
|
||||
|
||||
public ItemStat(Item item, OFFER_TYPE offerType) {
|
||||
this.offers = new TreeSet<>();
|
||||
this.offers = new ConcurrentSkipListSet<>();
|
||||
this.item = item;
|
||||
this.type = offerType;
|
||||
this.sum = 0;
|
||||
this.avg = Double.NaN;
|
||||
}
|
||||
|
||||
void put(Offer offer){
|
||||
synchronized void put(Offer offer){
|
||||
LOG.trace("Put offer {} to item stat {}", offer, this);
|
||||
assert offer.hasType(type) && offer.hasItem(item);
|
||||
if (offers.add(offer)){
|
||||
@@ -34,7 +35,7 @@ public class ItemStat {
|
||||
}
|
||||
}
|
||||
|
||||
void remove(Offer offer){
|
||||
synchronized void remove(Offer offer){
|
||||
LOG.trace("Remove offer {} from item stat {}", offer, this);
|
||||
assert offer.hasType(type) && offer.hasItem(item);
|
||||
if (offers.remove(offer)){
|
||||
@@ -49,7 +50,7 @@ public class ItemStat {
|
||||
}
|
||||
}
|
||||
|
||||
void update(Offer offer, double price){
|
||||
synchronized void update(Offer offer, double price){
|
||||
LOG.trace("Update offer {} from item stat {}", offer, this);
|
||||
assert offer.hasType(type) && offer.hasItem(item) && offers.contains(offer);
|
||||
double oldPrice = offer.getPrice();
|
||||
@@ -69,34 +70,34 @@ public class ItemStat {
|
||||
return item;
|
||||
}
|
||||
|
||||
public double getAvg(){
|
||||
public synchronized double getAvg(){
|
||||
return avg;
|
||||
}
|
||||
|
||||
public Offer getBest() {
|
||||
public synchronized Offer getBest() {
|
||||
if (offers.isEmpty()) return getFake();
|
||||
return type.getOrder() > 0 ? offers.first() : offers.last();
|
||||
}
|
||||
|
||||
public int getOffersCount(){
|
||||
public synchronized int getOffersCount(){
|
||||
return offers.size();
|
||||
}
|
||||
|
||||
public NavigableSet<Offer> getOffers() {
|
||||
public synchronized NavigableSet<Offer> getOffers() {
|
||||
return Collections.unmodifiableNavigableSet(offers);
|
||||
}
|
||||
|
||||
public Offer getMin() {
|
||||
public synchronized Offer getMin() {
|
||||
if (offers.isEmpty()) return getFake();
|
||||
return offers.first();
|
||||
}
|
||||
|
||||
public Offer getMax() {
|
||||
public synchronized Offer getMax() {
|
||||
if (offers.isEmpty()) return getFake();
|
||||
return offers.last();
|
||||
}
|
||||
|
||||
public boolean isEmpty(){
|
||||
public synchronized boolean isEmpty(){
|
||||
return offers.isEmpty();
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ public class Offer implements Comparable<Offer>{
|
||||
private Vendor vendor;
|
||||
private final Item item;
|
||||
private final OFFER_TYPE type;
|
||||
private double price;
|
||||
private volatile double price;
|
||||
|
||||
Offer(){
|
||||
item = null;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package ru.trader.core;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class SimpleVendor extends Vendor {
|
||||
|
||||
@@ -18,8 +19,8 @@ public class SimpleVendor extends Vendor {
|
||||
}
|
||||
|
||||
protected void initOffers(){
|
||||
sell = new HashMap<>();
|
||||
buy = new HashMap<>();
|
||||
sell = new ConcurrentHashMap<>(20, 0.9f, 2);
|
||||
buy = new ConcurrentHashMap<>(20, 0.9f, 2);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user