implement scorer
This commit is contained in:
45
core/src/main/java/ru/trader/analysis/FilteredMarket.java
Normal file
45
core/src/main/java/ru/trader/analysis/FilteredMarket.java
Normal file
@@ -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<Place> get(){
|
||||
return market.get().stream()
|
||||
.filter(p -> !filter.isFiltered(p));
|
||||
}
|
||||
|
||||
public Stream<Vendor> getVendors(){
|
||||
return get().flatMap(p -> p.get().stream())
|
||||
.filter(v -> !filter.isFiltered(v));
|
||||
}
|
||||
|
||||
public Collection<Item> getItems(){
|
||||
return market.getItems();
|
||||
}
|
||||
|
||||
public Stream<Offer> getSell(Item item){
|
||||
return getOffers(OFFER_TYPE.SELL, item);
|
||||
}
|
||||
|
||||
public Stream<Offer> getBuy(Item item){
|
||||
return getOffers(OFFER_TYPE.BUY, item);
|
||||
}
|
||||
|
||||
public Stream<Offer> getOffers(OFFER_TYPE offerType, Item item){
|
||||
return market.getStat(offerType, item).getOffers().stream()
|
||||
.filter(o -> !filter.isFiltered(o.getVendor(), true));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
102
core/src/main/java/ru/trader/analysis/Scorer.java
Normal file
102
core/src/main/java/ru/trader/analysis/Scorer.java
Normal file
@@ -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<Item, Offer> sellOffers;
|
||||
private final Map<Item, Offer> 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> 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<Order> sellOrders = vendor.getAllSellOffers().stream().flatMap(this::mapToOrder);
|
||||
Stream<Order> buyOrders = vendor.getAllBuyOffers().stream().flatMap(this::mapToOrder);
|
||||
return new Score(sellOrders, buyOrders);
|
||||
}
|
||||
|
||||
private Stream<Order> 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<Order> sell, Stream<Order> buy) {
|
||||
sellProfit = computeProfits(sell);
|
||||
buyProfit = computeProfits(buy);
|
||||
|
||||
long count = sell.limit(ordersCount).count();
|
||||
computeScore(count);
|
||||
}
|
||||
|
||||
private double computeProfits(Stream<Order> orders) {
|
||||
OptionalDouble profit = orders.sorted(Comparator.<Order>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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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) {
|
||||
|
||||
@@ -16,9 +16,13 @@ public class Order implements Comparable<Order> {
|
||||
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;
|
||||
}
|
||||
|
||||
15
core/src/main/java/ru/trader/core/Profile.java
Normal file
15
core/src/main/java/ru/trader/core/Profile.java
Normal file
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,12 @@ public class VendorsIterator implements Iterator<Vendor> {
|
||||
private Iterator<Vendor> vendors;
|
||||
private Vendor next;
|
||||
|
||||
public VendorsIterator(Iterator<Place> places, boolean includeTransit) {
|
||||
this.places = places;
|
||||
this.includeTransit = includeTransit;
|
||||
nextPlace();
|
||||
}
|
||||
|
||||
public VendorsIterator(Collection<Place> places, boolean includeTransit) {
|
||||
this.places = places.iterator();
|
||||
this.includeTransit = includeTransit;
|
||||
|
||||
1
core/src/test/resources/test3.xml
Normal file
1
core/src/test/resources/test3.xml
Normal file
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user