diff --git a/client/src/main/java/ru/trader/controllers/PowerPlayController.java b/client/src/main/java/ru/trader/controllers/PowerPlayController.java new file mode 100644 index 0000000..de841a4 --- /dev/null +++ b/client/src/main/java/ru/trader/controllers/PowerPlayController.java @@ -0,0 +1,193 @@ +package ru.trader.controllers; + +import javafx.collections.FXCollections; +import javafx.fxml.FXML; +import javafx.scene.control.*; +import org.controlsfx.control.CheckComboBox; +import ru.trader.Main; +import ru.trader.analysis.PowerPlayAnalyzator; +import ru.trader.core.*; +import ru.trader.model.*; +import ru.trader.model.support.BindingsHelper; +import ru.trader.view.support.PowerStateStringConverter; +import ru.trader.view.support.PowerStringConverter; +import ru.trader.view.support.autocomplete.AutoCompletion; +import ru.trader.view.support.autocomplete.CachedSuggestionProvider; +import ru.trader.view.support.autocomplete.SystemsProvider; + +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; + +public class PowerPlayController { + + @FXML + private TextField checkedSystemText; + private AutoCompletion checkedSystem; + @FXML + private TextField controlSystemText; + private AutoCompletion controlSystem; + @FXML + private ComboBox cbPower; + @FXML + private CheckComboBox cbStates; + + @FXML + private RadioButton rbIntersect; + @FXML + private RadioButton rbNear; + @FXML + private RadioButton rbMaxIntersect; + @FXML + private RadioButton rbExpansions; + @FXML + private RadioButton rbControlling; + @FXML + private ListView controlSystems; + @FXML + private TableView tblResults; + + private MarketModel world; + private ProfileModel profile; + private PowerPlayAnalyzator analyzator; + private final List result = FXCollections.observableArrayList(); + + + @FXML + private void initialize(){ + init(); + profile = MainController.getProfile(); + + cbPower.setConverter(new PowerStringConverter()); + cbPower.setItems(FXCollections.observableArrayList(POWER.values())); + cbStates.setConverter(new PowerStateStringConverter()); + cbStates.getItems().setAll(POWER_STATE.values()); + cbStates.getCheckModel().check(POWER_STATE.CONTROL); + cbStates.getCheckModel().check(POWER_STATE.HEADQUARTERS); + + BindingsHelper.setTableViewItems(tblResults, result); + + initListeners(); + } + + void init(){ + world = MainController.getWorld(); + analyzator = world.getPowerPlayAnalyzer(); + + SystemsProvider provider = world.getSystemsProvider(); + if (checkedSystem == null){ + checkedSystem = new AutoCompletion<>(checkedSystemText, new CachedSuggestionProvider<>(provider), ModelFabric.NONE_SYSTEM, provider.getConverter()); + } else { + checkedSystem.setSuggestions(provider.getPossibleSuggestions()); + checkedSystem.setConverter(provider.getConverter()); + } + if (controlSystem == null){ + controlSystem = new AutoCompletion<>(controlSystemText, new CachedSuggestionProvider<>(provider), ModelFabric.NONE_SYSTEM, provider.getConverter()); + } else { + controlSystem.setSuggestions(provider.getPossibleSuggestions()); + controlSystem.setConverter(provider.getConverter()); + } + } + + private void initListeners(){ + } + + + private void getIntersects(){ + Place starSystem = ModelFabric.get(checkedSystem.getValue()); + Collection controlls = getControlSystems(); + result.clear(); + if (starSystem != null && !controlls.isEmpty()){ + Collection intersects = analyzator.getIntersects(starSystem, controlls); + result.addAll(BindingsHelper.observableList(intersects, world.getModeler()::get)); + } + } + + private void getControlling(){ + Place starSystem = ModelFabric.get(checkedSystem.getValue()); + result.clear(); + if (starSystem != null){ + Collection controllings = analyzator.getControlling(starSystem); + result.addAll(BindingsHelper.observableList(controllings, world.getModeler()::get)); + } + } + + private void getNear(){ + Collection controlls = getControlSystems(); + result.clear(); + if (!controlls.isEmpty()){ + Collection near = analyzator.getNear(controlls); + result.addAll(BindingsHelper.observableList(near, world.getModeler()::get)); + } + } + + + @FXML + private void currentAsChecked(){ + checkedSystem.setValue(profile.getSystem()); + } + + @FXML + private void currentAsControl(){ + controlSystem.setValue(profile.getSystem()); + } + + + private Collection getControlSystems(){ + return controlSystems.getItems().stream().map(ModelFabric::get).collect(Collectors.toSet()); + } + + @FXML + private void search(){ + if (rbIntersect.isSelected()){ + getIntersects(); + } + if (rbControlling.isSelected()){ + getControlling(); + } + if (rbNear.isSelected()){ + getNear(); + } + + } + + + @FXML + private void addControlSystem(){ + SystemModel starSystem = controlSystem.getValue(); + if (!ModelFabric.isFake(starSystem)){ + controlSystems.getItems().add(starSystem); + } + POWER power = cbPower.getValue(); + if (power != null && power != POWER.NONE){ + StarSystemFilter filter = new StarSystemFilter(true); + filter.add(power); + cbStates.getCheckModel().getCheckedItems().forEach(filter::add); + controlSystems.getItems().addAll(world.getSystems(filter)); + } + cbPower.setValue(null); + controlSystem.setValue(ModelFabric.NONE_SYSTEM); + } + + @FXML + private void removeControlSystem(){ + int index = controlSystems.getSelectionModel().getSelectedIndex(); + if (index >= 0){ + controlSystems.getItems().remove(index); + } + } + + @FXML + private void clearControlSystems(){ + controlSystems.getItems().clear(); + } + + @FXML + private void copyToClipboard(){ + SystemModel starSystem = tblResults.getSelectionModel().getSelectedItem(); + if (starSystem != null){ + Main.copyToClipboard(starSystem.getName()); + } + } + +} diff --git a/client/src/main/java/ru/trader/model/MarketModel.java b/client/src/main/java/ru/trader/model/MarketModel.java index 4601f65..92dc949 100644 --- a/client/src/main/java/ru/trader/model/MarketModel.java +++ b/client/src/main/java/ru/trader/model/MarketModel.java @@ -10,6 +10,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import ru.trader.World; import ru.trader.analysis.CrawlerSpecificator; +import ru.trader.analysis.PowerPlayAnalyzator; import ru.trader.analysis.Route; import ru.trader.controllers.MainController; import ru.trader.controllers.ProgressController; @@ -69,6 +70,10 @@ public class MarketModel { return analyzer; } + public PowerPlayAnalyzator getPowerPlayAnalyzer() { + return new PowerPlayAnalyzator(market); + } + public ModelFabric getModeler() { return modeler; } @@ -213,6 +218,10 @@ public class MarketModel { return BindingsHelper.observableList(analyzer.getSystems(filter), modeler::get); } + public ObservableList getSystems(StarSystemFilter filter){ + return BindingsHelper.observableList(analyzer.getSystems(filter), modeler::get); + } + public void getOrders(StationModel from, Profile profile, Consumer> result) { getOrders(ModelFabric.NONE_SYSTEM, from, ModelFabric.NONE_SYSTEM, ModelFabric.NONE_STATION, profile, result); } diff --git a/client/src/main/resources/view/main.fxml b/client/src/main/resources/view/main.fxml index be7f0b3..bbde875 100644 --- a/client/src/main/resources/view/main.fxml +++ b/client/src/main/resources/view/main.fxml @@ -66,6 +66,9 @@ + + + diff --git a/client/src/main/resources/view/powerplay.fxml b/client/src/main/resources/view/powerplay.fxml new file mode 100644 index 0000000..ac4fedb --- /dev/null +++ b/client/src/main/resources/view/powerplay.fxml @@ -0,0 +1,96 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/src/main/java/ru/trader/analysis/PowerPlayAnalyzator.java b/core/src/main/java/ru/trader/analysis/PowerPlayAnalyzator.java index 5d2509e..1021e8a 100644 --- a/core/src/main/java/ru/trader/analysis/PowerPlayAnalyzator.java +++ b/core/src/main/java/ru/trader/analysis/PowerPlayAnalyzator.java @@ -3,6 +3,7 @@ package ru.trader.analysis; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import ru.trader.core.Market; +import ru.trader.core.POWER; import ru.trader.core.Place; import ru.trader.core.StarSystemFilter; @@ -11,6 +12,7 @@ import java.util.Comparator; import java.util.HashMap; import java.util.function.Predicate; import java.util.stream.Collectors; +import java.util.stream.Stream; public class PowerPlayAnalyzator { private final static Logger LOG = LoggerFactory.getLogger(PowerPlayAnalyzator.class); @@ -43,6 +45,10 @@ public class PowerPlayAnalyzator { return getIntersects(starSystem, market.get(), starSystems, CONTROLLING_RADIUS); } + public Collection getNear(Collection starSystems){ + Stream candidates = market.get().stream().filter(p -> p.getPower() == POWER.NONE); + return getNear(candidates, starSystems, CONTROLLING_RADIUS, CONTROLLING_RADIUS*2); + } public static Collection getControlling(Place starSystem, Collection starSystems, double radius){ return starSystems.stream() @@ -59,6 +65,13 @@ public class PowerPlayAnalyzator { .collect(Collectors.toList()); } + public static Collection getNear(Stream starSystems, Collection centers, double radius, double maxDistance){ + return starSystems.filter(new FarDropper(centers, maxDistance)) + .filter(intersectsAnyPredicate(centers, radius).negate()) + .sorted(new DistanceComparator(centers)) + .collect(Collectors.toList()); + } + public static Collection getIntersects(Place checkedSystem, Collection starSystems, Collection centers, double radius){ return starSystems.stream() .filter(new FarDropper(centers, radius)) diff --git a/core/src/main/java/ru/trader/core/MarketAnalyzer.java b/core/src/main/java/ru/trader/core/MarketAnalyzer.java index 758a0ab..f67039c 100644 --- a/core/src/main/java/ru/trader/core/MarketAnalyzer.java +++ b/core/src/main/java/ru/trader/core/MarketAnalyzer.java @@ -51,6 +51,10 @@ public class MarketAnalyzer { return market.get().filter(p -> !filter.isFiltered(p)).collect(Collectors.toList()); } + public List getSystems(StarSystemFilter filter){ + return market.get().filter(p -> !filter.isFiltered(p)).collect(Collectors.toList()); + } + public Collection getTop(int limit){ LOG.debug("Get top {}", limit); Collection places = getPlaces();