diff --git a/core/src/main/java/ru/trader/analysis/FilteredMarket.java b/core/src/main/java/ru/trader/analysis/FilteredMarket.java index 7f9b65d..1be1051 100644 --- a/core/src/main/java/ru/trader/analysis/FilteredMarket.java +++ b/core/src/main/java/ru/trader/analysis/FilteredMarket.java @@ -3,6 +3,7 @@ package ru.trader.analysis; import ru.trader.core.*; import java.util.Collection; +import java.util.HashMap; import java.util.NavigableSet; import java.util.function.Predicate; import java.util.stream.Stream; @@ -52,16 +53,12 @@ public class FilteredMarket { return vendor.has(SERVICE_TYPE.MARKET) || vendor.has(SERVICE_TYPE.BLACK_MARKET); } - private boolean isTransit(Vendor vendor){ - return vendor instanceof TransitVendor; - } - public Stream getMarkets(){ return getMarkets(false); } public Stream getMarkets(boolean withTransit){ - Predicate transitOrMarket = v -> withTransit && isTransit(v) || isMarket(v); + Predicate transitOrMarket = v -> withTransit && v.isTransit() || isMarket(v); if (disableFilter){ return market.getVendors().stream().filter(transitOrMarket); } @@ -91,8 +88,11 @@ public class FilteredMarket { if (disableFilter){ return res; } - return res.filter(o -> !filter.isFiltered(o.getVendor(), true)); + return res.filter(o -> !filter.isFiltered(o)); } + public FilteredVendor getFiltered(Vendor vendor){ + return new FilteredVendor(vendor, filter.getFilter(vendor)); + } } diff --git a/core/src/main/java/ru/trader/analysis/FilteredVendor.java b/core/src/main/java/ru/trader/analysis/FilteredVendor.java new file mode 100644 index 0000000..bbe1685 --- /dev/null +++ b/core/src/main/java/ru/trader/analysis/FilteredVendor.java @@ -0,0 +1,190 @@ +package ru.trader.analysis; + +import ru.trader.analysis.graph.Connectable; +import ru.trader.core.*; + +import java.util.Collection; +import java.util.stream.Collectors; + +public class FilteredVendor implements Vendor { + private final Vendor vendor; + private final VendorFilter filter; + + public FilteredVendor(Vendor vendor, VendorFilter filter) { + this.vendor = vendor; + this.filter = filter; + } + + @Override + public String getName() { + return vendor.getName(); + } + + @Override + public void setName(String name) { + vendor.setName(name); + } + + @Override + public String getFullName() { + return vendor.getFullName(); + } + + @Override + public Place getPlace() { + return vendor.getPlace(); + } + + @Override + public double getDistance() { + return vendor.getDistance(); + } + + @Override + public void setDistance(double distance) { + vendor.setDistance(distance); + } + + @Override + public FACTION getFaction() { + return vendor.getFaction(); + } + + @Override + public void setFaction(FACTION faction) { + vendor.setFaction(faction); + } + + @Override + public GOVERNMENT getGovernment() { + return vendor.getGovernment(); + } + + @Override + public void setGovernment(GOVERNMENT government) { + vendor.setGovernment(government); + } + + @Override + public void add(SERVICE_TYPE service) { + vendor.add(service); + } + + @Override + public void remove(SERVICE_TYPE service) { + vendor.remove(service); + } + + @Override + public boolean has(SERVICE_TYPE service) { + return vendor.has(service); + } + + @Override + public Collection getServices() { + return vendor.getServices(); + } + + @Override + public void add(Offer offer) { + vendor.add(offer); + } + + @Override + public Offer addOffer(OFFER_TYPE type, Item item, double price, long count) { + return vendor.addOffer(type, item, price, count); + } + + @Override + public void remove(Offer offer) { + vendor.remove(offer); + } + + @Override + public Collection get(OFFER_TYPE type) { + if (vendor.isTransit()) return vendor.get(type); + return vendor.get(type).stream().filter(o -> !filter.isFiltered(o)).collect(Collectors.toList()); + } + + @Override + public Offer get(OFFER_TYPE type, Item item) { + Offer offer = vendor.get(type, item); + if (offer == null || filter.isFiltered(offer)) return null; + return offer; + } + + @Override + public boolean has(OFFER_TYPE type, Item item) { + return vendor.has(type, item) && !filter.isFiltered(vendor, item, type); + } + + @Override + public Collection getAllSellOffers() { + if (vendor.isTransit()) return vendor.getAllSellOffers(); + return vendor.getAllSellOffers().stream().filter(o -> !filter.isFiltered(o)).collect(Collectors.toList()); + } + + @Override + public Collection getAllBuyOffers() { + if (vendor.isTransit()) return vendor.getAllBuyOffers(); + return vendor.getAllBuyOffers().stream().filter(o -> !filter.isFiltered(o)).collect(Collectors.toList()); + } + + @Override + public Offer getSell(Item item) { + Offer offer = vendor.getSell(item); + if (offer == null || filter.isFiltered(offer)) return null; + return offer; + } + + @Override + public Offer getBuy(Item item) { + Offer offer = vendor.getBuy(item); + if (offer == null || filter.isFiltered(offer)) return null; + return offer; + } + + @Override + public boolean hasSell(Item item) { + return vendor.hasSell(item) && !filter.isFiltered(vendor, item, OFFER_TYPE.SELL); + } + + @Override + public boolean hasBuy(Item item) { + return vendor.hasBuy(item) && !filter.isFiltered(vendor, item, OFFER_TYPE.BUY); + } + + @Override + public double getDistance(Vendor other) { + return vendor.getDistance(other); + } + + @Override + public boolean canRefill() { + return vendor.canRefill(); + } + + @Override + public void clear() { + vendor.clear(); + } + + @Override + public boolean isTransit() { + return vendor.isTransit(); + } + + @Override + public int compareTo(Connectable o) { + return vendor.compareTo(o); + } + + @Override + public String toString() { + return vendor.toString(); + } + + public Vendor unwrap(){ + return vendor; + } +} diff --git a/core/src/main/java/ru/trader/analysis/MarketUtils.java b/core/src/main/java/ru/trader/analysis/MarketUtils.java index 6c4dc1c..8ea6229 100644 --- a/core/src/main/java/ru/trader/analysis/MarketUtils.java +++ b/core/src/main/java/ru/trader/analysis/MarketUtils.java @@ -46,6 +46,7 @@ public class MarketUtils { public static List getOrders(Vendor seller, Vendor buyer){ LOG.trace("Get orders from {}, to {}", seller, buyer); List orders = new ArrayList<>(); + if (seller.isTransit() || buyer.isTransit()) return orders; for (Offer sell : seller.getAllSellOffers()) { Offer buy = buyer.getBuy(sell.getItem()); if (buy != null) { diff --git a/core/src/main/java/ru/trader/analysis/Scorer.java b/core/src/main/java/ru/trader/analysis/Scorer.java index ef0a88e..e1d14c3 100644 --- a/core/src/main/java/ru/trader/analysis/Scorer.java +++ b/core/src/main/java/ru/trader/analysis/Scorer.java @@ -165,4 +165,10 @@ public class Scorer { if (order.getProfit() <= 0) return Stream.empty(); return Stream.of(order); } + + public List getOrders(Vendor seller, Vendor buyer){ + FilteredVendor fSeller = market.getFiltered(seller); + FilteredVendor fBuyer = market.getFiltered(buyer); + return MarketUtils.getOrders(fSeller, fBuyer); + } } diff --git a/core/src/main/java/ru/trader/analysis/VendorsCrawler.java b/core/src/main/java/ru/trader/analysis/VendorsCrawler.java index 102d7b8..8a7b73d 100644 --- a/core/src/main/java/ru/trader/analysis/VendorsCrawler.java +++ b/core/src/main/java/ru/trader/analysis/VendorsCrawler.java @@ -87,7 +87,7 @@ public class VendorsCrawler extends Crawler { } else { Vendor seller = findMarket(); if (seller != null) { - orders = MarketUtils.getOrders(seller, edge.getTarget().getEntry()); + orders = getScorer().getOrders(seller, edge.getTarget().getEntry()); } } res.setOrders(MarketUtils.getStack(orders, balance, getScorer().getProfile().getShip().getCargo())); @@ -146,7 +146,7 @@ public class VendorsCrawler extends Crawler { if (orders == null){ Vendor seller = source.getEntry(); Vendor buyer = target.getEntry(); - orders = MarketUtils.getOrders(seller, buyer); + orders = getScorer().getOrders(seller, buyer); } return orders; } diff --git a/core/src/main/java/ru/trader/analysis/VendorsGraph.java b/core/src/main/java/ru/trader/analysis/VendorsGraph.java index c34693b..13b768e 100644 --- a/core/src/main/java/ru/trader/analysis/VendorsGraph.java +++ b/core/src/main/java/ru/trader/analysis/VendorsGraph.java @@ -297,7 +297,7 @@ public class VendorsGraph extends ConnectibleGraph { if (orders == null){ Vendor seller = source.getEntry(); Vendor buyer = target.getEntry(); - orders = MarketUtils.getOrders(seller, buyer); + orders = getScorer().getOrders(seller, buyer); } return orders; } diff --git a/core/src/main/java/ru/trader/core/Item.java b/core/src/main/java/ru/trader/core/Item.java index f7805ca..c6fff26 100644 --- a/core/src/main/java/ru/trader/core/Item.java +++ b/core/src/main/java/ru/trader/core/Item.java @@ -2,15 +2,23 @@ package ru.trader.core; import org.jetbrains.annotations.NotNull; +import java.util.Collection; import java.util.Objects; public interface Item extends Comparable { String getName(); void setName(String name); - boolean isIllegal(FACTION faction); + default boolean isIllegal(Vendor vendor){ + FACTION faction = vendor.getFaction(); + GOVERNMENT government = vendor.getGovernment(); + return faction != null && getIllegalFactions().contains(vendor.getFaction()) + || government != null && getIllegalGovernments().contains(government); + } + + Collection getIllegalFactions(); void setIllegal(FACTION faction, boolean illegal); - boolean isIllegal(GOVERNMENT government); + Collection getIllegalGovernments(); void setIllegal(GOVERNMENT government, boolean illegal); Group getGroup(); diff --git a/core/src/main/java/ru/trader/core/MarketFilter.java b/core/src/main/java/ru/trader/core/MarketFilter.java index 70a1e80..132d911 100644 --- a/core/src/main/java/ru/trader/core/MarketFilter.java +++ b/core/src/main/java/ru/trader/core/MarketFilter.java @@ -2,11 +2,9 @@ package ru.trader.core; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import ru.trader.analysis.FilteredVendor; -import java.util.ArrayList; -import java.util.Collection; -import java.util.EnumSet; -import java.util.Properties; +import java.util.*; public class MarketFilter { private final static Logger LOG = LoggerFactory.getLogger(MarketFilter.class); @@ -16,10 +14,18 @@ public class MarketFilter { private double distance; private final EnumSet services; private final Collection excludes; + private final VendorFilter defaultVendorFilter; + private final HashMap customFilteredVendors; public MarketFilter() { - services = EnumSet.noneOf(SERVICE_TYPE.class); - excludes = new ArrayList<>(); + this(new VendorFilter()); + } + + public MarketFilter(VendorFilter defaultVendorFilter) { + this.services = EnumSet.noneOf(SERVICE_TYPE.class); + this.excludes = new ArrayList<>(); + this.customFilteredVendors = new HashMap<>(); + this.defaultVendorFilter = defaultVendorFilter; } public Place getCenter() { @@ -78,6 +84,23 @@ public class MarketFilter { return excludes; } + private String getVendorKey(Vendor vendor){ + return vendor == null ? null : vendor.getFullName(); + } + + public void addFilter(Vendor vendor, VendorFilter vendorFilter){ + customFilteredVendors.put(getVendorKey(vendor), vendorFilter); + } + + public void removeFilter(Vendor vendor){ + customFilteredVendors.remove(getVendorKey(vendor)); + } + + public VendorFilter getFilter(Vendor vendor){ + VendorFilter filter = customFilteredVendors.get(getVendorKey(vendor)); + return filter != null ? filter : defaultVendorFilter; + } + public boolean isFiltered(Place place){ return center != null && center.getDistance(place) > radius; } @@ -96,6 +119,12 @@ public class MarketFilter { return false; } + public boolean isFiltered(Offer offer){ + if (isFiltered(offer.getVendor(), true)) return true; + VendorFilter filter = getFilter(offer.getVendor()); + return filter.isFiltered(offer); + } + public static MarketFilter buildFilter(Properties values, Market market){ MarketFilter filter = new MarketFilter(); String v = values.getProperty("filter.center", null); diff --git a/core/src/main/java/ru/trader/core/Offer.java b/core/src/main/java/ru/trader/core/Offer.java index a56c96f..a76757d 100644 --- a/core/src/main/java/ru/trader/core/Offer.java +++ b/core/src/main/java/ru/trader/core/Offer.java @@ -24,6 +24,12 @@ public interface Offer extends Comparable { return getItem().equals(item); } + default boolean isIllegal(){ + Vendor vendor = getVendor(); + Item item = getItem(); + return item.isIllegal(vendor); + } + @Override default int compareTo(@NotNull Offer other) { Objects.requireNonNull(other, "Not compare with null"); diff --git a/core/src/main/java/ru/trader/core/VendorFilter.java b/core/src/main/java/ru/trader/core/VendorFilter.java new file mode 100644 index 0000000..edb5bc2 --- /dev/null +++ b/core/src/main/java/ru/trader/core/VendorFilter.java @@ -0,0 +1,91 @@ +package ru.trader.core; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.Collection; + +public class VendorFilter { + private final static Logger LOG = LoggerFactory.getLogger(VendorFilter.class); + + private boolean disable; + private boolean skipIllegal; + private final Collection buyExcludes; + private final Collection sellExcludes; + + public VendorFilter() { + buyExcludes = new ArrayList<>(); + sellExcludes = new ArrayList<>(); + skipIllegal = false; + } + + public boolean isDisable() { + return disable; + } + + public void setDisable(boolean disable) { + this.disable = disable; + } + + public boolean isSkipIllegal() { + return skipIllegal; + } + + public void setSkipIllegal(boolean skipIllegal) { + this.skipIllegal = skipIllegal; + } + + public void addBuyExclude(Item item){ + buyExcludes.add(item); + } + + public void removeBuyExclude(Item item){ + buyExcludes.remove(item); + } + + public void clearBuyExcludes(){ + buyExcludes.clear(); + } + + public Collection getBuyExcludes(){ + return buyExcludes; + } + + public void addSellExclude(Item item){ + sellExcludes.add(item); + } + + public void removeSellExclude(Item item){ + sellExcludes.remove(item); + } + + public void clearSellExcludes(){ + sellExcludes.clear(); + } + + public Collection getSellExcludes(){ + return sellExcludes; + } + + public boolean isFiltered(Offer offer){ + if (disable) return false; + if (skipIllegal && offer.isIllegal()) return true; + switch (offer.getType()) { + case SELL: return sellExcludes.contains(offer.getItem()); + case BUY: return buyExcludes.contains(offer.getItem()); + } + return false; + } + + public boolean isFiltered(Vendor vendor, Item item, OFFER_TYPE offerType){ + if (disable) return false; + if (skipIllegal && (item.isIllegal(vendor))) return true; + switch (offerType) { + case SELL: return sellExcludes.contains(item); + case BUY: return buyExcludes.contains(item); + } + return false; + } + +} diff --git a/core/src/main/java/ru/trader/store/berkeley/ItemProxy.java b/core/src/main/java/ru/trader/store/berkeley/ItemProxy.java index e6f3ea1..cd7a0e4 100644 --- a/core/src/main/java/ru/trader/store/berkeley/ItemProxy.java +++ b/core/src/main/java/ru/trader/store/berkeley/ItemProxy.java @@ -6,6 +6,8 @@ import ru.trader.core.GOVERNMENT; import ru.trader.core.Group; import ru.trader.store.berkeley.entities.BDBItem; +import java.util.Collection; + public class ItemProxy extends AbstractItem { private final BDBItem item; private final BDBStore store; @@ -42,8 +44,8 @@ public class ItemProxy extends AbstractItem { } @Override - public boolean isIllegal(FACTION faction) { - return item.isIllegal(faction); + public Collection getIllegalFactions() { + return item.getIllegalFactions(); } @Override @@ -53,8 +55,8 @@ public class ItemProxy extends AbstractItem { } @Override - public boolean isIllegal(GOVERNMENT government) { - return item.isIllegal(government); + public Collection getIllegalGovernments() { + return item.getIllegalGovernments(); } @Override diff --git a/core/src/main/java/ru/trader/store/berkeley/entities/BDBItem.java b/core/src/main/java/ru/trader/store/berkeley/entities/BDBItem.java index 0ae9a8b..bd2bbf2 100644 --- a/core/src/main/java/ru/trader/store/berkeley/entities/BDBItem.java +++ b/core/src/main/java/ru/trader/store/berkeley/entities/BDBItem.java @@ -49,8 +49,8 @@ public class BDBItem { else fIllegals.remove(faction); } - public boolean isIllegal(FACTION faction) { - return fIllegals.contains(faction); + public Collection getIllegalFactions() { + return fIllegals; } public void setIllegal(GOVERNMENT government, boolean illegal) { @@ -58,8 +58,8 @@ public class BDBItem { else gIllegals.remove(government); } - public boolean isIllegal(GOVERNMENT government) { - return gIllegals.contains(government); + public Collection getIllegalGovernments() { + return gIllegals; } public String getGroupId() { diff --git a/core/src/main/java/ru/trader/store/simple/SimpleItem.java b/core/src/main/java/ru/trader/store/simple/SimpleItem.java index 961555a..f41e84a 100644 --- a/core/src/main/java/ru/trader/store/simple/SimpleItem.java +++ b/core/src/main/java/ru/trader/store/simple/SimpleItem.java @@ -5,6 +5,7 @@ import ru.trader.core.FACTION; import ru.trader.core.GOVERNMENT; import ru.trader.core.Group; +import java.util.Collection; import java.util.EnumSet; public class SimpleItem extends AbstractItem { @@ -39,8 +40,8 @@ public class SimpleItem extends AbstractItem { } @Override - public boolean isIllegal(FACTION faction) { - return fIllegals.contains(faction); + public Collection getIllegalFactions() { + return fIllegals; } @Override @@ -50,8 +51,8 @@ public class SimpleItem extends AbstractItem { } @Override - public boolean isIllegal(GOVERNMENT government) { - return gIllegals.contains(government); + public Collection getIllegalGovernments() { + return gIllegals; } @Override