From 60962b4958ecd06cac64c0b8af0fd71c972a5ea7 Mon Sep 17 00:00:00 2001 From: Mo Date: Sat, 8 Aug 2015 14:45:48 +0300 Subject: [PATCH] implement EDCE checker --- client/ext-resources/develop/log4j.properties | 2 + client/src/main/java/ru/trader/EDCE.java | 111 +++++++++++++++++- client/src/main/java/ru/trader/Main.java | 15 +-- .../main/java/ru/trader/ServicesManager.java | 51 ++++++++ .../controllers/StationEditorController.java | 24 ++-- .../java/ru/trader/model/MarketModel.java | 5 + .../trader/model/support/StationUpdater.java | 27 ++++- .../ru/trader/view/support/ViewUtils.java | 9 ++ 8 files changed, 224 insertions(+), 20 deletions(-) create mode 100644 client/src/main/java/ru/trader/ServicesManager.java diff --git a/client/ext-resources/develop/log4j.properties b/client/ext-resources/develop/log4j.properties index 5286f74..1de46de 100644 --- a/client/ext-resources/develop/log4j.properties +++ b/client/ext-resources/develop/log4j.properties @@ -3,3 +3,5 @@ log4j.rootLogger=DEBUG, stdout log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%p: %d{dd.MM.yyyy HH:mm:ss} (%F:%L) - %m%n + +log4j.logger.org.apache=INFO diff --git a/client/src/main/java/ru/trader/EDCE.java b/client/src/main/java/ru/trader/EDCE.java index c69b7ee..33008af 100644 --- a/client/src/main/java/ru/trader/EDCE.java +++ b/client/src/main/java/ru/trader/EDCE.java @@ -1,28 +1,45 @@ package ru.trader; +import javafx.application.Platform; +import javafx.util.Pair; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import ru.trader.controllers.Screeners; +import ru.trader.edce.Converter; import ru.trader.edce.EDCEParser; import ru.trader.edce.EDSession; +import ru.trader.edce.ED_SESSION_STATUS; import ru.trader.edce.entities.*; import ru.trader.edce.entities.System; import ru.trader.model.*; import ru.trader.model.support.StationUpdater; import java.io.IOException; +import java.util.Optional; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; public class EDCE { private final static Logger LOG = LoggerFactory.getLogger(EMDNUpdater.class); + private static ScheduledExecutorService executor; + private static ScheduledFuture checker; + private final ProfileModel profile; private final MarketModel world; private final StationUpdater updater; private final EDSession session; + private long interval; + private boolean forceUpdate; public EDCE(ProfileModel profile, MarketModel world) throws IOException, ClassNotFoundException { this.profile = profile; this.world = world; this.session = new EDSession(); this.updater = new StationUpdater(world); + interval = 5; + forceUpdate = true; } private void parseAndCheck(String json) { @@ -70,14 +87,50 @@ public class EDCE { } SystemModel sModel = profile.getSystem(); StationModel station = sModel.get(starport.getName()); - boolean found = station == ModelFabric.NONE_STATION; + boolean found = station != ModelFabric.NONE_STATION; if (!found){ + forceUpdate = false; LOG.info("Not found station {}, adding", starport.getName()); - station = sModel.add(starport.getName()); + updater.create(sModel); + updater.setName(starport.getName()); + station = updateStation(starport); + } else { + if (!profile.getStation().equals(station) || forceUpdate){ + forceUpdate = false; + updater.edit(station); + updateStation(starport); + } } profile.setStation(station); } + private StationModel updateStation(Starport starport) { + updater.setName(starport.getName()); + for (Commodity commodity : starport.getCommodities()) { + Optional item = world.getItem(Converter.getItemId(commodity.getId())); + if (item.isPresent()){ + Optional offer = updater.getOffer(item.get()); + if (offer.isPresent()){ + fillOffers(offer.get(), commodity); + } else { + LOG.error("Not found offer in updater, item: {}", item.get()); + } + } else { + LOG.warn("Not found item id: {}, name: {}, group: {}", commodity.getId(), commodity.getName(), commodity.getCategoryname()); + } + } + StationModel res = updater.commit(); + updater.reset(); + return res; + } + + private void fillOffers(StationUpdater.FakeOffer offer, Commodity commodity){ + offer.setBprice(commodity.getBuyPrice()); + offer.setSprice(commodity.getSellPrice()); + offer.setDemand(commodity.getDemand()); + offer.setSupply(commodity.getStock()); + } + private void checkShip(Ship ship){ if (ship == null){ LOG.warn("Don't read ship"); @@ -87,11 +140,63 @@ public class EDCE { profile.setShipTank(ship.getFuelCapacity()); } + public void run(){ + if (executor == null) executor = Executors.newSingleThreadScheduledExecutor(); + LOG.debug("Start EDCE checker each {} sec", interval); + checker = executor.scheduleAtFixedRate(new EDCEChecker(), interval, interval, TimeUnit.SECONDS); + } + + public void shutdown() throws IOException { + if (executor != null) { + LOG.debug("Shutdown EDCE checker"); + if (checker != null) checker.cancel(true); + executor.shutdownNow(); + executor = null; + checker = null; + } + session.close(); + } + private class EDCEChecker implements Runnable { + private boolean waiting; @Override public void run() { - session.readProfile(EDCE.this::parseAndCheck); + LOG.trace("EDCE check, waiting {}", waiting); + try { + if (waiting) return; + if (session.getLastStatus() == ED_SESSION_STATUS.OK) { + LOG.trace("Read profile from ED"); + session.readProfile(EDCE.this::parseAndCheck); + } + if (session.getLastStatus() == ED_SESSION_STATUS.LOGIN_REQUIRED) { + waiting = true; + Platform.runLater(() -> { + Optional> login = Screeners.showLogin(); + if (login.isPresent()) { + String email = login.get().getKey(); + String pass = login.get().getValue(); + session.login(email, pass); + if (session.getLastStatus() == ED_SESSION_STATUS.VERIFICATION_REQUIRED) { + LOG.trace("Verification required, send request"); + Optional code = Screeners.showVerifyCodeDialog(); + if (code.isPresent()) { + session.submitVerifyCode(code.get()); + session.login(email, pass); + } + } + if (session.getLastStatus() == ED_SESSION_STATUS.OK) { + LOG.trace("Read profile from ED"); + session.readProfile(EDCE.this::parseAndCheck); + } + } + waiting = false; + } + ); + } + } catch (Exception ex){ + LOG.error("",ex); + } } } diff --git a/client/src/main/java/ru/trader/Main.java b/client/src/main/java/ru/trader/Main.java index 807b3c5..bf3c6b8 100644 --- a/client/src/main/java/ru/trader/Main.java +++ b/client/src/main/java/ru/trader/Main.java @@ -5,7 +5,7 @@ import javafx.scene.Scene; import javafx.stage.Stage; import org.apache.log4j.PropertyConfigurator; import org.controlsfx.control.action.Action; -import org.controlsfx.dialog.*; +import org.controlsfx.dialog.Dialog; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import ru.trader.controllers.Screeners; @@ -36,7 +36,7 @@ public class Main extends Application { Main.primaryStage = primaryStage; loadMainScene(); loadResources(); - EMDNUpdater.init(); + ServicesManager.runAll(); primaryStage.show(); } @@ -69,19 +69,19 @@ public class Main extends Application { private static void loadMainScene() throws IOException { primaryStage.setTitle(Localization.getString("main.title")); primaryStage.setMinHeight(590); - primaryStage.setScene(new Scene(Screeners.newScreeners(Main.class.getResource("/view/main.fxml"),getUrl("style.css").toExternalForm()))); - primaryStage.setOnCloseRequest((we)->{ + primaryStage.setScene(new Scene(Screeners.newScreeners(Main.class.getResource("/view/main.fxml"), getUrl("style.css").toExternalForm()))); + primaryStage.setOnCloseRequest((we) -> { try { - if (World.getMarket().isChange()){ + if (World.getMarket().isChange()) { Action res = Screeners.showConfirm(Localization.getString("dialog.confirm.save")); if (res == Dialog.ACTION_YES) World.save(); else if (res == Dialog.ACTION_CANCEL) we.consume(); } - EMDNUpdater.shutdown(); + ServicesManager.stopAll(); SETTINGS.save(); Screeners.closeAll(); } catch (FileNotFoundException | UnsupportedEncodingException | XMLStreamException e) { - LOG.error("Error on save world",e); + LOG.error("Error on save world", e); Screeners.showException(e); } }); @@ -98,6 +98,7 @@ public class Main extends Application { Screeners.loadFilterStage(getUrl(("filter.fxml"))); Screeners.loadItemAddStage(getUrl("itemAdd.fxml")); Screeners.loadGroupAddStage(getUrl("groupAdd.fxml")); + Screeners.loadLoginStage(getUrl("login.fxml")); } private static URL getUrl(String filename) throws MalformedURLException { diff --git a/client/src/main/java/ru/trader/ServicesManager.java b/client/src/main/java/ru/trader/ServicesManager.java new file mode 100644 index 0000000..9b0bfd9 --- /dev/null +++ b/client/src/main/java/ru/trader/ServicesManager.java @@ -0,0 +1,51 @@ +package ru.trader; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import ru.trader.controllers.MainController; + +import java.io.IOException; + +public class ServicesManager { + private final static Logger LOG = LoggerFactory.getLogger(ServicesManager.class); + private static EDCE edce; + + + + public static void runAll(){ + runEDCE(); + runEMDN(); + } + + public static void stopAll(){ + stopEDCE(); + stopEMDN(); + } + + private static void runEDCE() { + try { + edce = new EDCE(MainController.getProfile(), MainController.getWorld()); + edce.run(); + } catch (IOException | ClassNotFoundException e) { + LOG.warn("Error on init EDCE", e); + } + } + + private static void stopEDCE(){ + if (edce != null){ + try { + edce.shutdown(); + } catch (IOException e) { + LOG.warn("Error on stop EDCE", e); + } + } + } + + private static void runEMDN() { + EMDNUpdater.init(); + } + + private static void stopEMDN(){ + EMDNUpdater.shutdown(); + } +} diff --git a/client/src/main/java/ru/trader/controllers/StationEditorController.java b/client/src/main/java/ru/trader/controllers/StationEditorController.java index 7ac3f57..02a56b3 100644 --- a/client/src/main/java/ru/trader/controllers/StationEditorController.java +++ b/client/src/main/java/ru/trader/controllers/StationEditorController.java @@ -8,7 +8,9 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import ru.trader.EMDNUpdater; import ru.trader.core.SERVICE_TYPE; -import ru.trader.model.*; +import ru.trader.model.ItemModel; +import ru.trader.model.StationModel; +import ru.trader.model.SystemModel; import ru.trader.model.support.StationUpdater; import ru.trader.view.support.Localization; import ru.trader.view.support.NumberField; @@ -67,7 +69,7 @@ public class StationEditorController { sell.setCellFactory(EditOfferCell.forTable(new PriceStringConverter(), true)); demand.setCellFactory(TextFieldCell.forTableColumn(new LongStringConverter())); supply.setCellFactory(TextFieldCell.forTableColumn(new LongStringConverter())); - name.setOnAction((v)->distance.requestFocus()); + name.setOnAction((v) -> distance.requestFocus()); distance.setOnAction((v) -> { items.requestFocus(); items.getSelectionModel().select(0, buy); @@ -132,15 +134,21 @@ public class StationEditorController { } public void showDialog(Parent parent, Parent content, StationModel station){ - showDialog(parent, content, station.getSystem(), station); - } - - public void showDialog(Parent parent, Parent content, SystemModel system, StationModel station){ if (dlg == null){ createDialog(parent, content); } - dlg.setTitle(Localization.getString(station == null ? "vEditor.title.add" : "vEditor.title.edit")); - updater.init(system, station); + dlg.setTitle(Localization.getString("vEditor.title.edit")); + updater.edit(station); + dlg.showAndWait(); + updater.reset(); + } + + public void showDialog(Parent parent, Parent content, SystemModel system){ + if (dlg == null){ + createDialog(parent, content); + } + dlg.setTitle(Localization.getString("vEditor.title.add")); + updater.create(system); dlg.showAndWait(); updater.reset(); } diff --git a/client/src/main/java/ru/trader/model/MarketModel.java b/client/src/main/java/ru/trader/model/MarketModel.java index 29b5059..58fae44 100644 --- a/client/src/main/java/ru/trader/model/MarketModel.java +++ b/client/src/main/java/ru/trader/model/MarketModel.java @@ -22,6 +22,7 @@ import ru.trader.services.RoutesSearchTask; import ru.trader.view.support.Localization; import java.util.Collection; +import java.util.Optional; import java.util.function.Consumer; @@ -125,6 +126,10 @@ public class MarketModel { return items; } + public Optional getItem(String id){ + return Optional.ofNullable(modeler.get(market.getItem(id))); + } + public ItemModel add(String name, GroupModel group) { ItemModel item = modeler.get(market.addItem(name, group.getGroup())); LOG.info("Add item {} to market {}", item, this); diff --git a/client/src/main/java/ru/trader/model/support/StationUpdater.java b/client/src/main/java/ru/trader/model/support/StationUpdater.java index e62c3bf..4a64fb3 100644 --- a/client/src/main/java/ru/trader/model/support/StationUpdater.java +++ b/client/src/main/java/ru/trader/model/support/StationUpdater.java @@ -9,6 +9,8 @@ import ru.trader.core.OFFER_TYPE; import ru.trader.core.SERVICE_TYPE; import ru.trader.model.*; +import java.util.Optional; + public class StationUpdater { private final static Logger LOG = LoggerFactory.getLogger(StationUpdater.class); @@ -35,7 +37,15 @@ public class StationUpdater { this.updateOnly = false; } - public void init(SystemModel system, StationModel station){ + public void edit(StationModel station){ + init(station.getSystem(), station); + } + + public void create(SystemModel system){ + init(system, null); + } + + private void init(SystemModel system, StationModel station){ LOG.debug("Init update of {}", station); this.station = station; this.system = system; @@ -76,6 +86,10 @@ public class StationUpdater { return offers; } + public Optional getOffer(final ItemModel item){ + return offers.stream().filter(o -> o.hasItem(item)).findAny(); + } + public StationModel getStation() { return station; } @@ -88,6 +102,10 @@ public class StationUpdater { return name; } + public void setName(String name) { + this.name.set(name); + } + public double getDistance() { return distance.get(); } @@ -96,6 +114,10 @@ public class StationUpdater { return distance; } + public void setDistance(double distance) { + this.distance.set(distance); + } + public BooleanProperty serviceProperty(SERVICE_TYPE service){ return services[service.ordinal()]; } @@ -104,7 +126,7 @@ public class StationUpdater { offers.add(index, new FakeOffer(item)); } - public void commit(){ + public StationModel commit(){ LOG.debug("Save changes of {}", station); if (isNew()) { Notificator notificator = market.getNotificator(); @@ -131,6 +153,7 @@ public class StationUpdater { } offers.forEach(FakeOffer::commit); } + return station; } public void reset(){ 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 b0ac561..405a297 100644 --- a/client/src/main/java/ru/trader/view/support/ViewUtils.java +++ b/client/src/main/java/ru/trader/view/support/ViewUtils.java @@ -2,6 +2,7 @@ package ru.trader.view.support; import com.sun.javafx.scene.control.skin.TableViewSkin; import com.sun.javafx.scene.control.skin.VirtualFlow; +import javafx.application.Platform; import javafx.collections.ObservableList; import javafx.scene.control.TablePosition; import javafx.scene.control.TableView; @@ -32,4 +33,12 @@ public class ViewUtils { } editNext(tableView); } + + public static void doFX(Runnable runnable){ + if (Platform.isFxApplicationThread()){ + runnable.run(); + } else { + Platform.runLater(runnable); + } + } }