add powerplay analyze interface to client
This commit is contained in:
@@ -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<SystemModel> checkedSystem;
|
||||
@FXML
|
||||
private TextField controlSystemText;
|
||||
private AutoCompletion<SystemModel> controlSystem;
|
||||
@FXML
|
||||
private ComboBox<POWER> cbPower;
|
||||
@FXML
|
||||
private CheckComboBox<POWER_STATE> cbStates;
|
||||
|
||||
@FXML
|
||||
private RadioButton rbIntersect;
|
||||
@FXML
|
||||
private RadioButton rbNear;
|
||||
@FXML
|
||||
private RadioButton rbMaxIntersect;
|
||||
@FXML
|
||||
private RadioButton rbExpansions;
|
||||
@FXML
|
||||
private RadioButton rbControlling;
|
||||
@FXML
|
||||
private ListView<SystemModel> controlSystems;
|
||||
@FXML
|
||||
private TableView<SystemModel> tblResults;
|
||||
|
||||
private MarketModel world;
|
||||
private ProfileModel profile;
|
||||
private PowerPlayAnalyzator analyzator;
|
||||
private final List<SystemModel> 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<Place> controlls = getControlSystems();
|
||||
result.clear();
|
||||
if (starSystem != null && !controlls.isEmpty()){
|
||||
Collection<Place> 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<Place> controllings = analyzator.getControlling(starSystem);
|
||||
result.addAll(BindingsHelper.observableList(controllings, world.getModeler()::get));
|
||||
}
|
||||
}
|
||||
|
||||
private void getNear(){
|
||||
Collection<Place> controlls = getControlSystems();
|
||||
result.clear();
|
||||
if (!controlls.isEmpty()){
|
||||
Collection<Place> 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<Place> 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());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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<SystemModel> getSystems(StarSystemFilter filter){
|
||||
return BindingsHelper.observableList(analyzer.getSystems(filter), modeler::get);
|
||||
}
|
||||
|
||||
public void getOrders(StationModel from, Profile profile, Consumer<ObservableList<OrderModel>> result) {
|
||||
getOrders(ModelFabric.NONE_SYSTEM, from, ModelFabric.NONE_SYSTEM, ModelFabric.NONE_STATION, profile, result);
|
||||
}
|
||||
|
||||
@@ -66,6 +66,9 @@
|
||||
<Tab fx:id="track" text="%main.tab.route">
|
||||
<fx:include fx:id="route" source="routeTrack.fxml"/>
|
||||
</Tab>
|
||||
<Tab text="Поверплей">
|
||||
<fx:include fx:id="pp" source="powerplay.fxml"/>
|
||||
</Tab>
|
||||
</TabPane>
|
||||
</center>
|
||||
|
||||
|
||||
96
client/src/main/resources/view/powerplay.fxml
Normal file
96
client/src/main/resources/view/powerplay.fxml
Normal file
@@ -0,0 +1,96 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import javafx.scene.control.*?>
|
||||
<?import javafx.scene.layout.*?>
|
||||
<?import org.controlsfx.glyphfont.*?>
|
||||
<?import javafx.scene.control.cell.PropertyValueFactory?>
|
||||
<?import ru.trader.view.support.cells.DistanceCell?>
|
||||
<?import org.controlsfx.control.CheckComboBox?>
|
||||
<VBox xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1"
|
||||
fx:controller="ru.trader.controllers.PowerPlayController"
|
||||
prefHeight="500" >
|
||||
<TitledPane text="Параметры анализа" collapsible="false">
|
||||
<HBox spacing="50" alignment="CENTER" minHeight="210" maxHeight="210">
|
||||
<VBox minWidth="250" maxWidth="250" spacing="4">
|
||||
<Label text="Проверяемая система:" />
|
||||
<HBox spacing="4" alignment="BASELINE_LEFT">
|
||||
<TextField fx:id="checkedSystemText" prefWidth="220"/>
|
||||
<Button minWidth="30" onAction="#currentAsChecked"><graphic><Glyph text="FontAwesome|MAP_MARKER"/></graphic></Button>
|
||||
</HBox>
|
||||
</VBox>
|
||||
<VBox minWidth="250" maxWidth="250" spacing="10" alignment="CENTER_LEFT">
|
||||
<fx:define><ToggleGroup fx:id="analyzeType" /></fx:define>
|
||||
<RadioButton fx:id="rbIntersect" text="Поиск пересечений" selected="true" toggleGroup="$analyzeType"/>
|
||||
<RadioButton fx:id="rbNear" text="Поиск ближайших без пересечений" selected="false" toggleGroup="$analyzeType"/>
|
||||
<RadioButton fx:id="rbMaxIntersect" text="Поиск с максимальным пересечением" selected="false" toggleGroup="$analyzeType"/>
|
||||
<RadioButton fx:id="rbExpansions" text="Ближайшие экспансии" selected="false" toggleGroup="$analyzeType"/>
|
||||
<RadioButton fx:id="rbControlling" text="Системы в подконтрольном радиусе" selected="false" toggleGroup="$analyzeType"/>
|
||||
<HBox alignment="CENTER">
|
||||
<Button prefWidth="120" text="Начать анализ" onAction="#search" />
|
||||
</HBox>
|
||||
</VBox>
|
||||
<VBox minWidth="250" maxWidth="250" spacing="4">
|
||||
<Label text="Контроллируемые системы:" />
|
||||
<HBox spacing="4">
|
||||
<TextField fx:id="controlSystemText" prefWidth="220"/>
|
||||
<Button minWidth="30" onAction="#currentAsControl"><graphic><Glyph text="FontAwesome|MAP_MARKER"/></graphic></Button>
|
||||
</HBox>
|
||||
<HBox HBox.hgrow="ALWAYS" spacing="4">
|
||||
<Label text="Cистемы силы:" minWidth="86" maxWidth="86" />
|
||||
<ComboBox fx:id="cbPower" minWidth="160"/>
|
||||
</HBox>
|
||||
<HBox HBox.hgrow="ALWAYS" spacing="4">
|
||||
<Label text="Состояние:" minWidth="86" maxWidth="86" />
|
||||
<CheckComboBox fx:id="cbStates" minWidth="160" />
|
||||
</HBox>
|
||||
<HBox spacing="4" alignment="CENTER" VBox.vgrow="ALWAYS" HBox.hgrow="ALWAYS">
|
||||
<ListView fx:id="controlSystems" HBox.hgrow="ALWAYS"/>
|
||||
<VBox spacing="4">
|
||||
<Button prefWidth="30" onAction="#addControlSystem"><graphic><Glyph text="FontAwesome|PLUS"/></graphic></Button>
|
||||
<Button prefWidth="30" onAction="#removeControlSystem"><graphic><Glyph text="FontAwesome|MINUS"/></graphic></Button>
|
||||
<Button prefWidth="30" onAction="#clearControlSystems"><graphic><Glyph text="FontAwesome|TRASH"/></graphic></Button>
|
||||
</VBox>
|
||||
</HBox>
|
||||
</VBox>
|
||||
</HBox>
|
||||
</TitledPane>
|
||||
<TitledPane text="Результаты анализа" collapsible="false">
|
||||
<TableView fx:id="tblResults">
|
||||
<columns>
|
||||
<TableColumn minWidth="200" text="%market.systems">
|
||||
<cellValueFactory><PropertyValueFactory property="name"/></cellValueFactory>
|
||||
</TableColumn>
|
||||
<TableColumn minWidth="200" text="%market.government">
|
||||
<cellValueFactory><PropertyValueFactory property="government"/></cellValueFactory>
|
||||
</TableColumn>
|
||||
<TableColumn minWidth="180" text="%market.allegiance">
|
||||
<cellValueFactory><PropertyValueFactory property="faction"/></cellValueFactory>
|
||||
</TableColumn>
|
||||
<TableColumn minWidth="110" text="%market.powerState">
|
||||
<cellValueFactory><PropertyValueFactory property="powerState"/></cellValueFactory>
|
||||
</TableColumn>
|
||||
<TableColumn minWidth="110" text="%market.power">
|
||||
<cellValueFactory><PropertyValueFactory property="power"/></cellValueFactory>
|
||||
</TableColumn>
|
||||
<TableColumn minWidth="110" text="%market.order.distance" fx:id="sortColumn" sortType="ASCENDING">
|
||||
<cellFactory><DistanceCell /></cellFactory>
|
||||
</TableColumn>
|
||||
<TableColumn minWidth="80" text="Типы площадок">
|
||||
</TableColumn>
|
||||
</columns>
|
||||
<columnResizePolicy>
|
||||
<TableView fx:constant="UNCONSTRAINED_RESIZE_POLICY"/>
|
||||
</columnResizePolicy>
|
||||
<sortOrder>
|
||||
<fx:reference source="sortColumn"/>
|
||||
</sortOrder>
|
||||
<contextMenu>
|
||||
<ContextMenu>
|
||||
<items>
|
||||
<MenuItem text="%dialog.button.copy" onAction="#copyToClipboard" />
|
||||
</items>
|
||||
</ContextMenu>
|
||||
</contextMenu>
|
||||
</TableView>
|
||||
</TitledPane>
|
||||
</VBox>
|
||||
@@ -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<Place> getNear(Collection<Place> starSystems){
|
||||
Stream<Place> candidates = market.get().stream().filter(p -> p.getPower() == POWER.NONE);
|
||||
return getNear(candidates, starSystems, CONTROLLING_RADIUS, CONTROLLING_RADIUS*2);
|
||||
}
|
||||
|
||||
public static Collection<Place> getControlling(Place starSystem, Collection<Place> starSystems, double radius){
|
||||
return starSystems.stream()
|
||||
@@ -59,6 +65,13 @@ public class PowerPlayAnalyzator {
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public static Collection<Place> getNear(Stream<Place> starSystems, Collection<Place> 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<Place> getIntersects(Place checkedSystem, Collection<Place> starSystems, Collection<Place> centers, double radius){
|
||||
return starSystems.stream()
|
||||
.filter(new FarDropper(centers, radius))
|
||||
|
||||
@@ -51,6 +51,10 @@ public class MarketAnalyzer {
|
||||
return market.get().filter(p -> !filter.isFiltered(p)).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public List<Place> getSystems(StarSystemFilter filter){
|
||||
return market.get().filter(p -> !filter.isFiltered(p)).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public Collection<Order> getTop(int limit){
|
||||
LOG.debug("Get top {}", limit);
|
||||
Collection<Place> places = getPlaces();
|
||||
|
||||
Reference in New Issue
Block a user