From bef5cc2f99456f1c2a6edf6423aae1bf111956c0 Mon Sep 17 00:00:00 2001 From: iMoHax Date: Wed, 15 Apr 2015 20:56:19 +0300 Subject: [PATCH] implement scorer --- .../ru/trader/analysis/FilteredMarket.java | 45 ++++++++ .../main/java/ru/trader/analysis/Scorer.java | 102 ++++++++++++++++++ .../java/ru/trader/core/MarketFilter.java | 5 + core/src/main/java/ru/trader/core/Order.java | 8 +- .../src/main/java/ru/trader/core/Profile.java | 15 +++ core/src/main/java/ru/trader/core/Ship.java | 29 +---- .../java/ru/trader/core/VendorsIterator.java | 6 ++ core/src/test/resources/test3.xml | 1 + 8 files changed, 185 insertions(+), 26 deletions(-) create mode 100644 core/src/main/java/ru/trader/analysis/FilteredMarket.java create mode 100644 core/src/main/java/ru/trader/analysis/Scorer.java create mode 100644 core/src/main/java/ru/trader/core/Profile.java create mode 100644 core/src/test/resources/test3.xml diff --git a/core/src/main/java/ru/trader/analysis/FilteredMarket.java b/core/src/main/java/ru/trader/analysis/FilteredMarket.java new file mode 100644 index 0000000..d2e22eb --- /dev/null +++ b/core/src/main/java/ru/trader/analysis/FilteredMarket.java @@ -0,0 +1,45 @@ +package ru.trader.analysis; + +import ru.trader.core.*; + +import java.util.Collection; +import java.util.stream.Stream; + +public class FilteredMarket { + private final Market market; + private final MarketFilter filter; + + public FilteredMarket(Market market, MarketFilter filter) { + this.market = market; + this.filter = filter; + } + + public Stream get(){ + return market.get().stream() + .filter(p -> !filter.isFiltered(p)); + } + + public Stream getVendors(){ + return get().flatMap(p -> p.get().stream()) + .filter(v -> !filter.isFiltered(v)); + } + + public Collection getItems(){ + return market.getItems(); + } + + public Stream getSell(Item item){ + return getOffers(OFFER_TYPE.SELL, item); + } + + public Stream getBuy(Item item){ + return getOffers(OFFER_TYPE.BUY, item); + } + + public Stream getOffers(OFFER_TYPE offerType, Item item){ + return market.getStat(offerType, item).getOffers().stream() + .filter(o -> !filter.isFiltered(o.getVendor(), true)); + } + + +} diff --git a/core/src/main/java/ru/trader/analysis/Scorer.java b/core/src/main/java/ru/trader/analysis/Scorer.java new file mode 100644 index 0000000..6759232 --- /dev/null +++ b/core/src/main/java/ru/trader/analysis/Scorer.java @@ -0,0 +1,102 @@ +package ru.trader.analysis; + +import ru.trader.core.*; + +import java.util.*; +import java.util.stream.Stream; + +public class Scorer { + private final Map sellOffers; + private final Map buyOffers; + private final FilteredMarket market; + private final Profile profile; + + private int ordersCount = 5; + + private double avgProfit; + + public Scorer(FilteredMarket market, Profile profile) { + this.market = market; + this.profile = profile; + sellOffers = new HashMap<>(100, 0.9f); + buyOffers = new HashMap<>(100, 0.9f); + market.getItems().parallelStream().forEach(this::fillOffers); + avgProfit = computeAvgProfit(); + } + + private void fillOffers(Item item){ + Optional offer = market.getSell(item).findFirst(); + if (offer.isPresent()){ + sellOffers.put(item, offer.get()); + } + offer = market.getBuy(item).findFirst(); + if (offer.isPresent()){ + buyOffers.put(item, offer.get()); + } + } + + public void setOrdersCount(int ordersCount) { + this.ordersCount = ordersCount; + } + + private double computeAvgProfit(){ + OptionalDouble avg = sellOffers.values().stream() + .flatMap(this::mapToOrder) + .mapToDouble(Order::getProfit) + .average(); + return avg.orElse(0); + } + + public Score getScore(Vendor vendor){ + Stream sellOrders = vendor.getAllSellOffers().stream().flatMap(this::mapToOrder); + Stream buyOrders = vendor.getAllBuyOffers().stream().flatMap(this::mapToOrder); + return new Score(sellOrders, buyOrders); + } + + private Stream mapToOrder(Offer offer) { + Offer sell; + Offer buy; + if (offer.getType() == OFFER_TYPE.SELL){ + sell = offer; + buy = buyOffers.get(offer.getItem()); + } else { + sell = sellOffers.get(offer.getItem()); + buy = offer; + } + if (sell == null || buy == null) return Stream.empty(); + Order order = new Order(sell, buy, profile.getBalance(), profile.getShip().getCargo()); + if (order.getProfit() <= 0) return Stream.empty(); + return Stream.of(order); + } + + public class Score { + private double sellProfit; + private double buyProfit; + private double score; + + public Score(Stream sell, Stream buy) { + sellProfit = computeProfits(sell); + buyProfit = computeProfits(buy); + + long count = sell.limit(ordersCount).count(); + computeScore(count); + } + + private double computeProfits(Stream orders) { + OptionalDouble profit = orders.sorted(Comparator.reverseOrder()) + .limit(ordersCount) + .mapToDouble(Order::getProfit) + .average(); + return profit.orElse(0); + } + + private void computeScore(long sellOrdersCount){ + score = (sellProfit + buyProfit)/2; + if (sellOrdersCount < ordersCount){ + score =- Math.abs(avgProfit-sellProfit) * (ordersCount - sellOrdersCount) / score; + } + + } + } + +} diff --git a/core/src/main/java/ru/trader/core/MarketFilter.java b/core/src/main/java/ru/trader/core/MarketFilter.java index 4625105..378d670 100644 --- a/core/src/main/java/ru/trader/core/MarketFilter.java +++ b/core/src/main/java/ru/trader/core/MarketFilter.java @@ -84,6 +84,11 @@ public class MarketFilter { } public boolean isFiltered(Vendor vendor){ + return isFiltered(vendor, false); + } + + public boolean isFiltered(Vendor vendor, boolean checkPlace){ + if (checkPlace && isFiltered(vendor.getPlace())) return true; if (distance > 0 && vendor.getDistance() > distance) return true; if (excludes.contains(vendor)) return true; for (SERVICE_TYPE service : services) { diff --git a/core/src/main/java/ru/trader/core/Order.java b/core/src/main/java/ru/trader/core/Order.java index 86f56e4..a341574 100644 --- a/core/src/main/java/ru/trader/core/Order.java +++ b/core/src/main/java/ru/trader/core/Order.java @@ -16,9 +16,13 @@ public class Order implements Comparable { this.profit = Double.NaN; } + public Order(Offer sell, Offer buy, double balance, long limit) { + this(sell, buy); + setMax(balance, limit); + } + public Order(Offer sell, Offer buy, long count) { - this.sell = sell; - this.buy = buy; + this(sell, buy); this.count = getMaxCount(sell, buy, count); this.profit = (buy.getPrice() - sell.getPrice()) * count; } diff --git a/core/src/main/java/ru/trader/core/Profile.java b/core/src/main/java/ru/trader/core/Profile.java new file mode 100644 index 0000000..c0b81c3 --- /dev/null +++ b/core/src/main/java/ru/trader/core/Profile.java @@ -0,0 +1,15 @@ +package ru.trader.core; + +public class Profile { + + private double balance; + private Ship ship; + + public double getBalance() { + return balance; + } + + public Ship getShip() { + return ship; + } +} diff --git a/core/src/main/java/ru/trader/core/Ship.java b/core/src/main/java/ru/trader/core/Ship.java index 70feb01..6fb906d 100644 --- a/core/src/main/java/ru/trader/core/Ship.java +++ b/core/src/main/java/ru/trader/core/Ship.java @@ -2,35 +2,23 @@ package ru.trader.core; public class Ship { - private double balance; - private long cargo; + private int cargo; private double engine; - private int jumps; - public Ship(double balance, long cargo, double engine, int jumps) { - this.balance = balance; + public Ship(int cargo, double engine) { this.cargo = cargo; this.engine = engine; - this.jumps = jumps; } public static Ship copyOf(Ship other){ - return new Ship(other.balance, other.cargo, other.engine, other.jumps); + return new Ship(other.cargo, other.engine); } - public double getBalance() { - return balance; - } - - public void setBalance(double balance) { - this.balance = balance; - } - - public long getCargo() { + public int getCargo() { return cargo; } - public void setCargo(long cargo) { + public void setCargo(int cargo) { this.cargo = cargo; } @@ -42,11 +30,4 @@ public class Ship { this.engine = engine; } - public int getJumps() { - return jumps; - } - - public void setJumps(int jumps) { - this.jumps = jumps; - } } diff --git a/core/src/main/java/ru/trader/core/VendorsIterator.java b/core/src/main/java/ru/trader/core/VendorsIterator.java index 7074f75..a5a83fe 100644 --- a/core/src/main/java/ru/trader/core/VendorsIterator.java +++ b/core/src/main/java/ru/trader/core/VendorsIterator.java @@ -13,6 +13,12 @@ public class VendorsIterator implements Iterator { private Iterator vendors; private Vendor next; + public VendorsIterator(Iterator places, boolean includeTransit) { + this.places = places; + this.includeTransit = includeTransit; + nextPlace(); + } + public VendorsIterator(Collection places, boolean includeTransit) { this.places = places.iterator(); this.includeTransit = includeTransit; diff --git a/core/src/test/resources/test3.xml b/core/src/test/resources/test3.xml new file mode 100644 index 0000000..d791e7c --- /dev/null +++ b/core/src/test/resources/test3.xml @@ -0,0 +1 @@ + \ No newline at end of file