Archived
0

implement saving vendor filters, modify filter screen

This commit is contained in:
iMoHax
2016-03-16 16:56:49 +03:00
parent 10bdb62164
commit 63299d825c
10 changed files with 523 additions and 59 deletions

View File

@@ -7,6 +7,8 @@ import ru.trader.core.Market;
import ru.trader.core.MarketFilter; import ru.trader.core.MarketFilter;
import ru.trader.core.Profile; import ru.trader.core.Profile;
import ru.trader.core.Ship; import ru.trader.core.Ship;
import ru.trader.store.json.FiltersStore;
import ru.trader.store.json.JsonStore;
import javax.swing.*; import javax.swing.*;
import java.io.*; import java.io.*;
@@ -21,6 +23,8 @@ public class Settings {
private Profile profile; private Profile profile;
private final EDCESettings edce; private final EDCESettings edce;
private final HelperSettings helper; private final HelperSettings helper;
private final JsonStore jsonStore;
private MarketFilter filter;
public Settings() { public Settings() {
@@ -28,6 +32,7 @@ public class Settings {
profile = new Profile(new Ship()); profile = new Profile(new Ship());
edce = new EDCESettings(); edce = new EDCESettings();
helper = new HelperSettings(); helper = new HelperSettings();
jsonStore = new JsonStore();
} }
public Settings(File file) { public Settings(File file) {
@@ -35,16 +40,19 @@ public class Settings {
profile = new Profile(new Ship()); profile = new Profile(new Ship());
edce = new EDCESettings(); edce = new EDCESettings();
helper = new HelperSettings(); helper = new HelperSettings();
jsonStore = new JsonStore();
} }
public void load(Market market) { public void load(Market market) {
try (InputStream is = new FileInputStream(file)) { try (InputStream is = new FileInputStream(file)) {
values.load(is); values.load(is);
filter = jsonStore.getFilter(market);
} catch (FileNotFoundException e) { } catch (FileNotFoundException e) {
LOG.warn("File {} not found", file); LOG.warn("File {} not found", file);
} catch (IOException e) { } catch (IOException e) {
LOG.error("Error on load settings", e); LOG.error("Error on load settings", e);
} }
if (filter == null) filter = new MarketFilter();
profile = Profile.readFrom(values, market); profile = Profile.readFrom(values, market);
edce.readFrom(values); edce.readFrom(values);
helper.readFrom(values); helper.readFrom(values);
@@ -56,8 +64,9 @@ public class Settings {
edce.writeTo(values); edce.writeTo(values);
helper.writeTo(values); helper.writeTo(values);
values.store(os, "settings"); values.store(os, "settings");
jsonStore.saveFilter(filter);
} catch (IOException e) { } catch (IOException e) {
LOG.error("Error on load settings", e); LOG.error("Error on save settings", e);
} }
} }
@@ -143,11 +152,11 @@ public class Settings {
} }
public MarketFilter getFilter(Market market){ public MarketFilter getFilter(Market market){
return MarketFilter.buildFilter(values, market); return filter;
} }
public void setFilter(MarketFilter filter){ public void setFilter(MarketFilter filter){
filter.writeTo(values); this.filter = filter;
} }
public Profile getProfile() { public Profile getProfile() {

View File

@@ -5,18 +5,16 @@ import javafx.fxml.FXML;
import javafx.scene.Parent; import javafx.scene.Parent;
import javafx.scene.control.*; import javafx.scene.control.*;
import javafx.util.Pair; import javafx.util.Pair;
import org.controlsfx.control.CheckComboBox;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import ru.trader.core.MarketFilter; import ru.trader.core.*;
import ru.trader.core.SERVICE_TYPE;
import ru.trader.core.VendorFilter;
import ru.trader.model.MarketModel; import ru.trader.model.MarketModel;
import ru.trader.model.ModelFabric; import ru.trader.model.ModelFabric;
import ru.trader.model.StationModel; import ru.trader.model.StationModel;
import ru.trader.model.SystemModel; import ru.trader.model.SystemModel;
import ru.trader.model.support.BindingsHelper; import ru.trader.model.support.BindingsHelper;
import ru.trader.view.support.Localization; import ru.trader.view.support.*;
import ru.trader.view.support.NumberField;
import ru.trader.view.support.autocomplete.AutoCompletion; import ru.trader.view.support.autocomplete.AutoCompletion;
import ru.trader.view.support.autocomplete.CachedSuggestionProvider; import ru.trader.view.support.autocomplete.CachedSuggestionProvider;
import ru.trader.view.support.autocomplete.SystemsProvider; import ru.trader.view.support.autocomplete.SystemsProvider;
@@ -41,23 +39,14 @@ public class FilterController {
@FXML @FXML
private ComboBox<String> station; private ComboBox<String> station;
@FXML @FXML
private CheckBox cbMarket; private CheckComboBox<STATION_TYPE> stationTypes;
@FXML @FXML
private CheckBox cbBlackMarket; private CheckComboBox<SERVICE_TYPE> services;
@FXML @FXML
private CheckBox cbRefuel; private CheckComboBox<FACTION> factions;
@FXML @FXML
private CheckBox cbRepair; private CheckComboBox<GOVERNMENT> governments;
@FXML
private CheckBox cbMunition;
@FXML
private CheckBox cbOutfit;
@FXML
private CheckBox cbShipyard;
@FXML
private CheckBox cbMediumLandpad;
@FXML
private CheckBox cbLargeLandpad;
@FXML @FXML
private ListView<StationModel> excludes; private ListView<StationModel> excludes;
@FXML @FXML
@@ -76,6 +65,14 @@ public class FilterController {
@FXML @FXML
private void initialize(){ private void initialize(){
init(); init();
stationTypes.setConverter(new StationTypeStringConverter());
stationTypes.getItems().setAll(STATION_TYPE.values());
services.setConverter(new ServiceTypeStringConverter());
services.getItems().setAll(SERVICE_TYPE.values());
factions.setConverter(new FactionStringConverter());
factions.getItems().setAll(FACTION.values());
governments.setConverter(new GovernmentStringConverter());
governments.getItems().setAll(GOVERNMENT.values());
excludes.setCellFactory(new CustomListCell<>(StationModel::getFullName)); excludes.setCellFactory(new CustomListCell<>(StationModel::getFullName));
system.valueProperty().addListener((ov, o, n) -> { system.valueProperty().addListener((ov, o, n) -> {
station.setItems(n.getStationNamesList()); station.setItems(n.getStationNamesList());
@@ -134,15 +131,22 @@ public class FilterController {
center.setValue(market.getModeler().get(filter.getCenter())); center.setValue(market.getModeler().get(filter.getCenter()));
radius.setValue(filter.getRadius()); radius.setValue(filter.getRadius());
distance.setValue(filter.getDistance()); distance.setValue(filter.getDistance());
cbMarket.setSelected(filter.has(SERVICE_TYPE.MARKET)); stationTypes.getCheckModel().clearChecks();
cbBlackMarket.setSelected(filter.has(SERVICE_TYPE.BLACK_MARKET)); for (STATION_TYPE stationType : filter.getTypes()) {
cbRefuel.setSelected(filter.has(SERVICE_TYPE.REFUEL)); stationTypes.getCheckModel().check(stationType);
cbMunition.setSelected(filter.has(SERVICE_TYPE.MUNITION)); }
cbRepair.setSelected(filter.has(SERVICE_TYPE.REPAIR)); services.getCheckModel().clearChecks();
cbOutfit.setSelected(filter.has(SERVICE_TYPE.OUTFIT)); for (SERVICE_TYPE service : filter.getServices()) {
cbShipyard.setSelected(filter.has(SERVICE_TYPE.SHIPYARD)); services.getCheckModel().check(service);
cbMediumLandpad.setSelected(filter.has(SERVICE_TYPE.MEDIUM_LANDPAD)); }
cbLargeLandpad.setSelected(filter.has(SERVICE_TYPE.LARGE_LANDPAD)); factions.getCheckModel().clearChecks();
for (FACTION faction : filter.getFactions()) {
factions.getCheckModel().check(faction);
}
governments.getCheckModel().clearChecks();
for (GOVERNMENT government : filter.getGovernments()) {
governments.getCheckModel().check(government);
}
excludes.setItems(BindingsHelper.observableList(filter.getExcludes(), market.getModeler()::get)); excludes.setItems(BindingsHelper.observableList(filter.getExcludes(), market.getModeler()::get));
vFilters.getItems().clear(); vFilters.getItems().clear();
for (Map.Entry<String, VendorFilter> entry : filter.getVendorFilters().entrySet()) { for (Map.Entry<String, VendorFilter> entry : filter.getVendorFilters().entrySet()) {
@@ -165,15 +169,14 @@ public class FilterController {
filter.setCenter(ModelFabric.isFake(s) ? null : ModelFabric.get(s)); filter.setCenter(ModelFabric.isFake(s) ? null : ModelFabric.get(s));
filter.setRadius(radius.getValue().doubleValue()); filter.setRadius(radius.getValue().doubleValue());
filter.setDistance(distance.getValue().doubleValue()); filter.setDistance(distance.getValue().doubleValue());
if (cbMarket.isSelected()) filter.add(SERVICE_TYPE.MARKET); else filter.remove(SERVICE_TYPE.MARKET); filter.clearTypes();
if (cbBlackMarket.isSelected()) filter.add(SERVICE_TYPE.BLACK_MARKET); else filter.remove(SERVICE_TYPE.BLACK_MARKET); stationTypes.getCheckModel().getCheckedItems().forEach(filter::add);
if (cbRefuel.isSelected()) filter.add(SERVICE_TYPE.REFUEL); else filter.remove(SERVICE_TYPE.REFUEL); filter.clearServices();
if (cbMunition.isSelected()) filter.add(SERVICE_TYPE.MUNITION); else filter.remove(SERVICE_TYPE.MUNITION); services.getCheckModel().getCheckedItems().forEach(filter::add);
if (cbRepair.isSelected()) filter.add(SERVICE_TYPE.REPAIR); else filter.remove(SERVICE_TYPE.REPAIR); filter.clearFactions();
if (cbOutfit.isSelected()) filter.add(SERVICE_TYPE.OUTFIT); else filter.remove(SERVICE_TYPE.OUTFIT); factions.getCheckModel().getCheckedItems().forEach(filter::add);
if (cbShipyard.isSelected()) filter.add(SERVICE_TYPE.SHIPYARD); else filter.remove(SERVICE_TYPE.SHIPYARD); filter.clearGovernments();
if (cbMediumLandpad.isSelected()) filter.add(SERVICE_TYPE.MEDIUM_LANDPAD); else filter.remove(SERVICE_TYPE.MEDIUM_LANDPAD); governments.getCheckModel().getCheckedItems().forEach(filter::add);
if (cbLargeLandpad.isSelected()) filter.add(SERVICE_TYPE.LARGE_LANDPAD); else filter.remove(SERVICE_TYPE.LARGE_LANDPAD);
filter.clearExcludes(); filter.clearExcludes();
excludes.getItems().forEach(st -> filter.addExclude(ModelFabric.get(st))); excludes.getItems().forEach(st -> filter.addExclude(ModelFabric.get(st)));
filter.clearVendorFilters(); filter.clearVendorFilters();

View File

@@ -11,6 +11,7 @@ market.station.name=Station
market.allegiance=Allegiance market.allegiance=Allegiance
market.government=Government market.government=Government
market.economic=Economy market.economic=Economy
market.station.services=Services
market.station.type=Station type market.station.type=Station type
# Offer # Offer

View File

@@ -11,6 +11,7 @@ market.station.name=\u0421\u0442\u0430\u043D\u0446\u0438\u044F
market.allegiance=\u041F\u0440\u0438\u043D\u0430\u0434\u043B\u0435\u0436\u043D\u043E\u0441\u0442\u044C market.allegiance=\u041F\u0440\u0438\u043D\u0430\u0434\u043B\u0435\u0436\u043D\u043E\u0441\u0442\u044C
market.government=\u0424\u043E\u0440\u043C\u0430 \u043F\u0440\u0430\u0432\u043B\u0435\u043D\u0438\u044F market.government=\u0424\u043E\u0440\u043C\u0430 \u043F\u0440\u0430\u0432\u043B\u0435\u043D\u0438\u044F
market.economic=\u042D\u043A\u043E\u043D\u043E\u043C\u0438\u043A\u0430 market.economic=\u042D\u043A\u043E\u043D\u043E\u043C\u0438\u043A\u0430
market.station.services=\u0421\u0435\u0440\u0432\u0438\u0441\u044B
market.station.type=\u0422\u0438\u043F \u0441\u0442\u0430\u043D\u0446\u0438\u0438 market.station.type=\u0422\u0438\u043F \u0441\u0442\u0430\u043D\u0446\u0438\u0438
# Offer # Offer

View File

@@ -2,6 +2,7 @@
<?import javafx.scene.layout.*?> <?import javafx.scene.layout.*?>
<?import org.controlsfx.glyphfont.*?> <?import org.controlsfx.glyphfont.*?>
<?import ru.trader.view.support.NumberField?> <?import ru.trader.view.support.NumberField?>
<?import org.controlsfx.control.CheckComboBox?>
<GridPane xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="ru.trader.controllers.FilterController" <GridPane xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="ru.trader.controllers.FilterController"
styleClass="dialog" vgap="4" hgap="8"> styleClass="dialog" vgap="4" hgap="8">
<columnConstraints> <columnConstraints>
@@ -15,20 +16,28 @@
<NumberField fx:id="radius" GridPane.columnIndex="1" GridPane.rowIndex="2" /> <NumberField fx:id="radius" GridPane.columnIndex="1" GridPane.rowIndex="2" />
<Label text="%filter.distance" GridPane.rowIndex="3" /> <Label text="%filter.distance" GridPane.rowIndex="3" />
<NumberField fx:id="distance" GridPane.columnIndex="1" GridPane.rowIndex="3" /> <NumberField fx:id="distance" GridPane.columnIndex="1" GridPane.rowIndex="3" />
<Label text="%filter.services" GridPane.rowIndex="4" /> <HBox GridPane.rowIndex="4" GridPane.columnSpan="2" spacing="10" alignment="CENTER">
<TilePane hgap="5" vgap="5" tileAlignment="BASELINE_LEFT" prefColumns="2" GridPane.columnIndex="1" GridPane.rowIndex="4" > <VBox prefWidth="200" alignment="CENTER">
<CheckBox fx:id="cbMarket" text="%services.MARKET"/> <Label text="%market.station.type"/>
<CheckBox fx:id="cbBlackMarket" text="%services.BLACK_MARKET"/> <CheckComboBox fx:id="stationTypes" maxWidth="200" />
<CheckBox fx:id="cbRefuel" text="%services.REFUEL"/> </VBox>
<CheckBox fx:id="cbRepair" text="%services.REPAIR"/> <VBox prefWidth="200" alignment="CENTER">
<CheckBox fx:id="cbMunition" text="%services.MUNITION"/> <Label text="%market.station.services"/>
<CheckBox fx:id="cbOutfit" text="%services.OUTFIT"/> <CheckComboBox fx:id="services" maxWidth="200" />
<CheckBox fx:id="cbShipyard" text="%services.SHIPYARD"/> </VBox>
<CheckBox fx:id="cbMediumLandpad" text="%services.MEDIUM_LANDPAD"/> </HBox>
<CheckBox fx:id="cbLargeLandpad" text="%services.LARGE_LANDPAD"/> <HBox GridPane.rowIndex="5" GridPane.columnSpan="2" spacing="10" alignment="CENTER">
</TilePane> <VBox prefWidth="200" alignment="CENTER">
<Label text="%filter.excludes" GridPane.rowIndex="5" /> <Label text="%market.allegiance"/>
<VBox GridPane.rowIndex="6" spacing="4"> <CheckComboBox fx:id="factions" maxWidth="200" />
</VBox>
<VBox prefWidth="200" alignment="CENTER">
<Label text="%market.government"/>
<CheckComboBox fx:id="governments" maxWidth="200" />
</VBox>
</HBox>
<Label text="%filter.excludes" GridPane.rowIndex="6" />
<VBox GridPane.rowIndex="7" spacing="4">
<TextField fx:id="systemText" minWidth="180"/> <TextField fx:id="systemText" minWidth="180"/>
<ComboBox fx:id="station" minWidth="180"/> <ComboBox fx:id="station" minWidth="180"/>
<HBox spacing="2" alignment="BASELINE_RIGHT"> <HBox spacing="2" alignment="BASELINE_RIGHT">
@@ -37,10 +46,10 @@
<Button prefWidth="30" onAction="#clean"><graphic><Glyph text="FontAwesome|TRASH_ALT"/></graphic></Button> <Button prefWidth="30" onAction="#clean"><graphic><Glyph text="FontAwesome|TRASH_ALT"/></graphic></Button>
</HBox> </HBox>
</VBox> </VBox>
<ListView fx:id="excludes" GridPane.rowIndex="6" GridPane.columnIndex="1" maxHeight="120"/> <ListView fx:id="excludes" GridPane.rowIndex="7" GridPane.columnIndex="1" maxHeight="120"/>
<Label text="Фильтры на товары:" GridPane.rowIndex="7" /> <Label text="Фильтры на товары:" GridPane.rowIndex="8" />
<VBox GridPane.rowIndex="8" spacing="4"> <VBox GridPane.rowIndex="9" spacing="4">
<TextField fx:id="vFilterSystemText" minWidth="180"/> <TextField fx:id="vFilterSystemText" minWidth="180"/>
<ComboBox fx:id="vFilterStation" minWidth="180"/> <ComboBox fx:id="vFilterStation" minWidth="180"/>
<HBox spacing="2" alignment="BASELINE_RIGHT"> <HBox spacing="2" alignment="BASELINE_RIGHT">
@@ -50,8 +59,8 @@
<Button prefWidth="30" onAction="#cleanVendorFilters"><graphic><Glyph text="FontAwesome|TRASH_ALT"/></graphic></Button> <Button prefWidth="30" onAction="#cleanVendorFilters"><graphic><Glyph text="FontAwesome|TRASH_ALT"/></graphic></Button>
</HBox> </HBox>
<Button prefWidth="180" text="Глобальный фильтр" onAction="#editDefaultVendorFilter"/> <Button prefWidth="180" text="Глобальный фильтр" onAction="#editDefaultVendorFilter"/>
</VBox> </VBox>
<ListView fx:id="vFilters" GridPane.rowIndex="8" GridPane.columnIndex="1" maxHeight="120"/> <ListView fx:id="vFilters" GridPane.rowIndex="9" GridPane.columnIndex="1" maxHeight="120"/>
</GridPane> </GridPane>

View File

@@ -40,6 +40,10 @@
<groupId>com.sleepycat</groupId> <groupId>com.sleepycat</groupId>
<artifactId>je</artifactId> <artifactId>je</artifactId>
</dependency> </dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
</dependencies> </dependencies>
<packaging>jar</packaging> <packaging>jar</packaging>

View File

@@ -11,7 +11,10 @@ public class MarketFilter {
private Place center; private Place center;
private double radius; private double radius;
private double distance; private double distance;
private final EnumSet<STATION_TYPE> types;
private final EnumSet<SERVICE_TYPE> services; private final EnumSet<SERVICE_TYPE> services;
private final EnumSet<FACTION> factions;
private final EnumSet<GOVERNMENT> governments;
private final Collection<Vendor> excludes; private final Collection<Vendor> excludes;
private final VendorFilter defaultVendorFilter; private final VendorFilter defaultVendorFilter;
private final HashMap<String, VendorFilter> customFilteredVendors; private final HashMap<String, VendorFilter> customFilteredVendors;
@@ -21,7 +24,10 @@ public class MarketFilter {
} }
public MarketFilter(VendorFilter defaultVendorFilter) { public MarketFilter(VendorFilter defaultVendorFilter) {
this.types = EnumSet.noneOf(STATION_TYPE.class);
this.services = EnumSet.noneOf(SERVICE_TYPE.class); this.services = EnumSet.noneOf(SERVICE_TYPE.class);
this.factions = EnumSet.noneOf(FACTION.class);
this.governments = EnumSet.noneOf(GOVERNMENT.class);
this.excludes = new ArrayList<>(); this.excludes = new ArrayList<>();
this.customFilteredVendors = new HashMap<>(); this.customFilteredVendors = new HashMap<>();
this.defaultVendorFilter = defaultVendorFilter; this.defaultVendorFilter = defaultVendorFilter;
@@ -51,6 +57,22 @@ public class MarketFilter {
this.distance = distance; this.distance = distance;
} }
public void add(STATION_TYPE type){
types.add(type);
}
public void remove(STATION_TYPE type){
types.remove(type);
}
public void clearTypes(){
types.clear();
}
public Collection<STATION_TYPE> getTypes(){
return types;
}
public void add(SERVICE_TYPE service){ public void add(SERVICE_TYPE service){
services.add(service); services.add(service);
} }
@@ -67,6 +89,14 @@ public class MarketFilter {
return services.contains(service); return services.contains(service);
} }
public void clearServices(){
services.clear();
}
public Collection<SERVICE_TYPE> getServices(){
return services;
}
public void addExclude(Vendor vendor){ public void addExclude(Vendor vendor){
excludes.add(vendor); excludes.add(vendor);
} }
@@ -83,6 +113,38 @@ public class MarketFilter {
return excludes; return excludes;
} }
public void add(FACTION faction){
factions.add(faction);
}
public void remove(FACTION faction){
factions.remove(faction);
}
public void clearFactions(){
factions.clear();
}
public Collection<FACTION> getFactions(){
return factions;
}
public void add(GOVERNMENT government){
governments.add(government);
}
public void remove(GOVERNMENT government){
governments.remove(government);
}
public void clearGovernments(){
governments.clear();
}
public Collection<GOVERNMENT> getGovernments(){
return governments;
}
public static String getVendorKey(Vendor vendor){ public static String getVendorKey(Vendor vendor){
return vendor == null ? null : vendor.getFullName(); return vendor == null ? null : vendor.getFullName();
} }
@@ -132,6 +194,12 @@ public class MarketFilter {
if (checkPlace && isFiltered(vendor.getPlace())) return true; if (checkPlace && isFiltered(vendor.getPlace())) return true;
if (distance > 0 && vendor.getDistance() > distance) return true; if (distance > 0 && vendor.getDistance() > distance) return true;
if (excludes.contains(vendor)) return true; if (excludes.contains(vendor)) return true;
STATION_TYPE stationType = vendor.getType();
if (stationType != null && !types.isEmpty() && !types.contains(stationType)) return true;
FACTION faction = vendor.getFaction();
if (faction != null && !factions.isEmpty() && !factions.contains(faction)) return true;
GOVERNMENT government = vendor.getGovernment();
if (government != null && !governments.isEmpty() && !governments.contains(vendor.getGovernment())) return true;
for (SERVICE_TYPE service : services) { for (SERVICE_TYPE service : services) {
if (!vendor.has(service)) return true; if (!vendor.has(service)) return true;
} }
@@ -205,7 +273,10 @@ public class MarketFilter {
"center=" + center + "center=" + center +
", radius=" + radius + ", radius=" + radius +
", distance=" + distance + ", distance=" + distance +
", types=" + types +
", services=" + services + ", services=" + services +
", factions=" + factions +
", governments=" + governments +
", excludes=" + excludes + ", excludes=" + excludes +
'}'; '}';
} }

View File

@@ -0,0 +1,223 @@
package ru.trader.store.json;
import com.fasterxml.jackson.core.JsonEncoding;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ru.trader.core.*;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
public class FiltersStore {
private static final Logger LOG = LoggerFactory.getLogger(FiltersStore.class);
private static final String DISABLE_FIELD = "disable";
private static final String CENTER_FIELD = "center";
private static final String RADIUS_FIELD = "radius";
private static final String DISTANCE_FIELD = "distance";
private static final String TYPES_FIELD = "types";
private static final String SERVICES_FIELD = "services";
private static final String FACTIONS_FIELD = "factions";
private static final String GOVERNMENTS_FIELD = "governments";
private static final String EXCLUDE_VENDORS_FIELD = "excludes";
private static final String SYSTEM_FIELD = "system";
private static final String STATION_FIELD = "station";
private static final String DEFAULT_VENDOR_FILTER_KEY = "default";
private static final String VENDOR_FILTERS_FIELD = "stations";
private static final String LEGAL_ONLY_FIELD = "legalOnly";
private static final String DONT_SELL_FIELD = "notSell";
private static final String DONT_BUY_FIELD = "notBuy";
private static final String SELL_FILTER_FIELD = "excludeSell";
private static final String BUY_FILTER_FIELD = "excludeBuy";
private final ObjectMapper objectMapper;
public FiltersStore(ObjectMapper objectMapper) {
this.objectMapper = objectMapper;
}
public void write(MarketFilter filter, File file) throws IOException {
try (JsonGenerator generator = objectMapper.getFactory().createGenerator(file, JsonEncoding.UTF8)){
write(filter, generator);
generator.flush();
}
}
private void write(MarketFilter filter, JsonGenerator generator) throws IOException {
generator.writeStartObject();
Place center = filter.getCenter();
generator.writeStringField(CENTER_FIELD, center != null ? center.getName() : "");
generator.writeNumberField(RADIUS_FIELD, filter.getRadius());
generator.writeNumberField(DISTANCE_FIELD, filter.getDistance());
generator.writeArrayFieldStart(TYPES_FIELD);
for (STATION_TYPE stationType : filter.getTypes()) {
generator.writeString(stationType.toString());
}
generator.writeEndArray();
generator.writeArrayFieldStart(SERVICES_FIELD);
for (SERVICE_TYPE service : filter.getServices()) {
generator.writeString(service.toString());
}
generator.writeEndArray();
generator.writeArrayFieldStart(FACTIONS_FIELD);
for (FACTION faction : filter.getFactions()) {
generator.writeString(faction.toString());
}
generator.writeEndArray();
generator.writeArrayFieldStart(GOVERNMENTS_FIELD);
for (GOVERNMENT government : filter.getGovernments()) {
generator.writeString(government.toString());
}
generator.writeEndArray();
generator.writeArrayFieldStart(EXCLUDE_VENDORS_FIELD);
for (Vendor vendor : filter.getExcludes()) {
generator.writeStartObject();
generator.writeStringField(SYSTEM_FIELD, vendor.getPlace().getName());
generator.writeStringField(STATION_FIELD, vendor.getName());
generator.writeEndObject();
}
generator.writeEndArray();
generator.writeObjectFieldStart(VENDOR_FILTERS_FIELD);
write(DEFAULT_VENDOR_FILTER_KEY, filter.getDefaultVendorFilter(), generator);
for (Map.Entry<String, VendorFilter> entry : filter.getVendorFilters().entrySet()) {
write(entry.getKey(), entry.getValue(), generator);
}
generator.writeEndObject();
generator.writeEndObject();
}
private void write(String key, VendorFilter filter, JsonGenerator generator) throws IOException {
generator.writeObjectFieldStart(key);
generator.writeBooleanField(DISABLE_FIELD, filter.isDisable());
generator.writeBooleanField(LEGAL_ONLY_FIELD, filter.isSkipIllegal());
generator.writeBooleanField(DONT_SELL_FIELD, filter.isDontSell());
generator.writeBooleanField(DONT_BUY_FIELD, filter.isDontBuy());
generator.writeArrayFieldStart(SELL_FILTER_FIELD);
for (Item item : filter.getSellExcludes()) {
generator.writeString(item.getName());
}
generator.writeEndArray();
generator.writeArrayFieldStart(BUY_FILTER_FIELD);
for (Item item : filter.getBuyExcludes()) {
generator.writeString(item.getName());
}
generator.writeEndArray();
generator.writeEndObject();
}
public MarketFilter read(Market market, File file) throws IOException {
MarketFilter filter = new MarketFilter();
if (!file.exists()){
LOG.warn("Don't exists filters file {}", file);
} else {
try (JsonParser parser = objectMapper.getFactory().createParser(file)){
read(filter, market, parser);
}
}
return filter;
}
private void read(MarketFilter filter, Market market, JsonParser parser) throws IOException {
JsonNode node = parser.readValueAsTree();
String placeName = node.get(CENTER_FIELD).asText();
if (!placeName.isEmpty()){
Place place = market.get(placeName);
if (place != null){
filter.setCenter(place);
} else {
LOG.warn("Parse filter error: Don't found system {}", placeName);
}
}
filter.setRadius(node.get(RADIUS_FIELD).asDouble());
filter.setDistance(node.get(DISTANCE_FIELD).asDouble());
Iterator<JsonNode> iterator = node.get(TYPES_FIELD).elements();
while (iterator.hasNext()) {
JsonNode n = iterator.next();
STATION_TYPE value = STATION_TYPE.valueOf(n.asText());
filter.add(value);
}
iterator = node.get(SERVICES_FIELD).elements();
while (iterator.hasNext()) {
JsonNode n = iterator.next();
SERVICE_TYPE value = SERVICE_TYPE.valueOf(n.asText());
filter.add(value);
}
iterator = node.get(FACTIONS_FIELD).elements();
while (iterator.hasNext()) {
JsonNode n = iterator.next();
FACTION value = FACTION.valueOf(n.asText());
filter.add(value);
}
iterator = node.get(GOVERNMENTS_FIELD).elements();
while (iterator.hasNext()) {
JsonNode n = iterator.next();
GOVERNMENT value = GOVERNMENT.valueOf(n.asText());
filter.add(value);
}
iterator = node.get(EXCLUDE_VENDORS_FIELD).elements();
while (iterator.hasNext()) {
JsonNode n = iterator.next();
placeName = n.get(SYSTEM_FIELD).asText();
Place place = market.get(placeName);
if (place == null){
LOG.warn("Parse filter error: Don't found system {}", placeName);
} else {
String vendorName = n.get(STATION_FIELD).asText();
Vendor vendor = place.get(vendorName);
if (vendor == null){
LOG.warn("Parse filter error: Don't found vendor {} in system {}", vendorName, place);
} else {
filter.addExclude(vendor);
}
}
}
Iterator<Map.Entry<String,JsonNode>> fi = node.get(VENDOR_FILTERS_FIELD).fields();
while (fi.hasNext()){
Map.Entry<String,JsonNode> n = fi.next();
if (DEFAULT_VENDOR_FILTER_KEY.equals(n.getKey())){
VendorFilter vendorFilter = filter.getDefaultVendorFilter();
read(vendorFilter, market, n.getValue());
} else {
VendorFilter vendorFilter = new VendorFilter();
read(vendorFilter, market, n.getValue());
filter.addFilter(n.getKey(), vendorFilter);
}
}
}
private void read(VendorFilter filter, Market market, JsonNode node){
filter.setDisable(node.get(DISABLE_FIELD).asBoolean());
filter.setSkipIllegal(node.get(LEGAL_ONLY_FIELD).asBoolean());
filter.dontSell(node.get(DONT_SELL_FIELD).asBoolean());
filter.dontBuy(node.get(DONT_BUY_FIELD).asBoolean());
Iterator<JsonNode> iterator = node.get(SELL_FILTER_FIELD).elements();
while (iterator.hasNext()) {
JsonNode n = iterator.next();
String itemName = n.asText();
Item item = market.getItem(itemName);
if (item == null){
LOG.warn("Parse filter error: Don't found item {}", itemName);
} else {
filter.addSellExclude(item);
}
}
iterator = node.get(BUY_FILTER_FIELD).elements();
while (iterator.hasNext()) {
JsonNode n = iterator.next();
String itemName = n.asText();
Item item = market.getItem(itemName);
if (item == null){
LOG.warn("Parse filter error: Don't found item {}", itemName);
} else {
filter.addBuyExclude(item);
}
}
}
}

View File

@@ -0,0 +1,27 @@
package ru.trader.store.json;
import com.fasterxml.jackson.databind.ObjectMapper;
import ru.trader.core.Market;
import ru.trader.core.MarketFilter;
import java.io.File;
import java.io.IOException;
public class JsonStore {
private final ObjectMapper objectMapper;
private static final String FILTERS_FILE_NAME = "filters.cfg";
public JsonStore() {
objectMapper = new ObjectMapper();
}
public MarketFilter getFilter(Market market) throws IOException {
FiltersStore store = new FiltersStore(objectMapper);
return store.read(market, new File(FILTERS_FILE_NAME));
}
public void saveFilter(MarketFilter filter) throws IOException {
FiltersStore store = new FiltersStore(objectMapper);
store.write(filter, new File(FILTERS_FILE_NAME));
}
}

View File

@@ -0,0 +1,116 @@
package ru.trader.store.json;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import ru.trader.core.*;
import ru.trader.store.simple.Store;
import java.io.File;
import java.io.InputStream;
import java.util.Map;
public class FiltersStoreTest extends Assert {
private static final File file = new File("filters-test.json");
private static final ObjectMapper objectMapper = new ObjectMapper();
private Market world;
private Place ithaca;
private Place lhs3262;
private Place morgor;
private Place lhs3006;
private Item gold;
private Item tea;
@Before
public void setUp() throws Exception {
InputStream is = getClass().getResourceAsStream("/world.xml");
world = Store.loadFromFile(is);
gold = world.getItem("gold");
tea = world.getItem("tea");
ithaca = world.get("Ithaca");
lhs3262 = world.get("LHS 3262");
morgor = world.get("Morgor");
lhs3006 = world.get("LHS 3006");
}
private MarketFilter createFilter(){
Vendor ithaca_st = ithaca.get().iterator().next();
Vendor lhs3262_st = lhs3262.get().iterator().next();
Vendor lhs3006_st = lhs3006.get().iterator().next();
Vendor morgor_st = morgor.get().iterator().next();
MarketFilter filter = new MarketFilter();
filter.setCenter(ithaca);
filter.setRadius(15.22);
filter.setDistance(2456.44);
filter.add(STATION_TYPE.CORIOLIS_STARPORT);
filter.add(STATION_TYPE.ORBIS_STARPORT);
filter.add(SERVICE_TYPE.MARKET);
filter.add(SERVICE_TYPE.BLACK_MARKET);
filter.add(FACTION.EMPIRE);
filter.add(GOVERNMENT.ANARCHY);
filter.add(GOVERNMENT.COMMUNISM);
filter.addExclude(morgor_st);
filter.addExclude(ithaca_st);
VendorFilter vendorFilter = new VendorFilter();
vendorFilter.setDisable(true);
vendorFilter.setSkipIllegal(true);
vendorFilter.dontBuy(true);
vendorFilter.addSellExclude(gold);
vendorFilter.addSellExclude(tea);
vendorFilter.addBuyExclude(tea);
filter.addFilter(lhs3006_st, vendorFilter);
vendorFilter = filter.getDefaultVendorFilter();
vendorFilter.dontSell(true);
vendorFilter.addBuyExclude(gold);
vendorFilter = new VendorFilter();
vendorFilter.setSkipIllegal(true);
filter.addFilter(lhs3262_st, vendorFilter);
return filter;
}
@Test
public void testSaveLoadFilter() throws Exception {
MarketFilter filter = createFilter();
FiltersStore store = new FiltersStore(objectMapper);
store.write(filter, file);
MarketFilter actual = store.read(world, file);
assertFilter(filter, actual);
}
private void assertFilter(MarketFilter expected, MarketFilter actual){
assertEquals(expected.getCenter(), actual.getCenter());
assertEquals(expected.getRadius(), actual.getRadius(), 0.0001);
assertEquals(expected.getDistance(), actual.getDistance(), 0.0001);
assertEquals(expected.getTypes(), actual.getTypes());
assertEquals(expected.getServices(), actual.getServices());
assertEquals(expected.getFactions(), actual.getFactions());
assertEquals(expected.getGovernments(), actual.getGovernments());
assertEquals(expected.getExcludes(), actual.getExcludes());
assertFilter(expected.getDefaultVendorFilter(), actual.getDefaultVendorFilter());
Map<String, VendorFilter> expectedFilters = expected.getVendorFilters();
Map<String, VendorFilter> actualFilters = actual.getVendorFilters();
assertEquals(expectedFilters.size(), actualFilters.size());
for (Map.Entry<String, VendorFilter> entry : expectedFilters.entrySet()) {
VendorFilter act = actualFilters.get(entry.getKey());
assertFilter(entry.getValue(), act);
}
}
private void assertFilter(VendorFilter expected, VendorFilter actual){
assertEquals(expected.isDisable(), actual.isDisable());
assertEquals(expected.isSkipIllegal(), actual.isSkipIllegal());
assertEquals(expected.isDontBuy(), actual.isDontBuy());
assertEquals(expected.isDontSell(), actual.isDontSell());
assertEquals(expected.getBuyExcludes(), actual.getBuyExcludes());
assertEquals(expected.getSellExcludes(), actual.getSellExcludes());
}
@After
public void tearDown() throws Exception {
file.delete();
}
}