Archived
0

use new route searcher in market analyzer

This commit is contained in:
iMoHax
2015-07-16 13:22:23 +03:00
parent 100e6794f9
commit e654d87e3c
7 changed files with 334 additions and 422 deletions

View File

@@ -6,7 +6,7 @@ import ru.trader.core.Vendor;
import java.util.*;
public class Route {
public class Route implements Comparable<Route> {
private final static Logger LOG = LoggerFactory.getLogger(Route.class);
private final List<RouteEntry> entries;
@@ -31,6 +31,10 @@ public class Route {
return entries;
}
public RouteEntry get(int index) {
return entries.get(index);
}
void setBalance(double balance){
this.balance = balance;
}
@@ -115,6 +119,11 @@ public class Route {
LOG.trace("new stats profit={}, distance={}, lands={}, fuel={}, score={}", profit, distance, lands, fuel, score);
}
@Override
public int compareTo(Route o) {
return Double.compare(score, o.score);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;

View File

@@ -2,13 +2,14 @@ package ru.trader.analysis;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ru.trader.analysis.graph.ConnectibleEdge;
import ru.trader.analysis.graph.Crawler;
import ru.trader.analysis.graph.Edge;
import ru.trader.analysis.graph.*;
import ru.trader.core.Order;
import ru.trader.core.Place;
import ru.trader.core.Profile;
import ru.trader.core.Vendor;
import java.util.*;
import java.util.function.Predicate;
public class RouteSearcher {
private final static Logger LOG = LoggerFactory.getLogger(RouteSearcher.class);
@@ -18,33 +19,78 @@ public class RouteSearcher {
this.scorer = scorer;
}
public List<Route> getRoutes(Vendor from, Vendor to, Collection<Vendor> vendors){
return search(from, to, vendors);
public List<Edge<Place>> getPath(Place from, Place to, Collection<Place> places){
List<List<Edge<Place>>> res = search(from, to, places, 1, null);
return res.isEmpty() ? null : res.get(0);
}
public List<List<Edge<Place>>> getPaths(Place from, Collection<Place> places){
Predicate<Edge<Place>> isFoundFunc = e -> places.parallelStream().filter(e::isConnect).findFirst().isPresent();
return search(from, from, places, scorer.getProfile().getRoutesCount(), isFoundFunc);
}
public List<List<Edge<Place>>> getPaths(Place from, Place to, Collection<Place> places){
return search(from, to, places, scorer.getProfile().getRoutesCount(), null);
}
private List<List<Edge<Place>>> search(Place source, Place target, Collection<Place> places, int count, Predicate<Edge<Place>> isFoundFunc){
Profile profile = scorer.getProfile();
LOG.trace("Start search path from {} to {} ", source, target);
ConnectibleGraph<Place> graph = new ConnectibleGraph<>(profile);
LOG.trace("Build connectible graph");
graph.build(source, places);
LOG.trace("Graph is builds");
List<List<Edge<Place>>> paths = new ArrayList<>();
Crawler<Place> crawler = isFoundFunc != null ? new CCrawler<>(graph, isFoundFunc, paths::add) : new CCrawler<>(graph, paths::add);
crawler.setMaxSize(profile.getJumps());
if (profile.getPathPriority() == Profile.PATH_PRIORITY.FAST){
crawler.findFast(target, count);
} else {
crawler.findMin(target, count);
}
return paths;
}
public List<Route> getRoutes(Collection<Vendor> fVendors, Collection<Vendor> vendors){
return getRoutes(fVendors, vendors, vendors);
}
public List<Route> getRoutes(Collection<Vendor> fVendors, Collection<Vendor> toVendors, Collection<Vendor> vendors){
List<Route> res = new LimitedQueue<>(scorer.getProfile().getRoutesCount());
int count = (int) Math.ceil(scorer.getProfile().getRoutesCount() / fVendors.size());
Predicate<Edge<Vendor>> isFoundFunc = e -> toVendors.parallelStream().filter(e::isConnect).findFirst().isPresent();
for (Vendor fromVendor : fVendors) {
count = count / toVendors.size();
Collection<Route> routes = search(fromVendor, fromVendor, vendors, count, isFoundFunc);
res.addAll(routes);
}
return res;
}
public List<Route> getRoutes(Vendor from, Collection<Vendor> vendors){
return search(from, null, vendors);
Predicate<Edge<Vendor>> isFoundFunc = e -> vendors.parallelStream().filter(e::isConnect).findFirst().isPresent();
return search(from, from, vendors, scorer.getProfile().getRoutesCount(), isFoundFunc);
}
private List<Route> search(Vendor source, Vendor target, Collection<Vendor> vendors){
LOG.trace("Start search route to {} from {}", source, target);
public List<Route> getRoutes(Vendor from, Vendor to, Collection<Vendor> vendors){
return getRoutes(from, to, vendors, scorer.getProfile().getRoutesCount());
}
public List<Route> getRoutes(Vendor source, Vendor target, Collection<Vendor> vendors, int count){
return search(source, target, vendors, count, null);
}
private List<Route> search(Vendor source, Vendor target, Collection<Vendor> vendors, int count, Predicate<Edge<Vendor>> isFoundFunc){
LOG.trace("Start search route from {} to {}", source, target);
VendorsGraph vGraph = new VendorsGraph(scorer);
LOG.trace("Build vendors graph");
vGraph.build(source, vendors);
LOG.trace("Graph is builds");
RouteCollector collector = new RouteCollector();
Crawler<Vendor> crawler = vGraph.crawler(collector::add);
Crawler<Vendor> crawler = isFoundFunc != null ? vGraph.crawler(isFoundFunc, collector::add) : vGraph.crawler(collector::add);
crawler.setMaxSize(scorer.getProfile().getLands());
if (target == null){
int count = vGraph.getProfile().getRoutesCount() / vendors.size();
for (Vendor vendor : vendors) {
crawler.findMin(vendor, count);
}
} else {
crawler.findMin(target, vGraph.getProfile().getRoutesCount());
}
crawler.findMin(target, count);
return collector.get();
}
private class RouteCollector {

View File

@@ -2,161 +2,114 @@ package ru.trader.core;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ru.trader.graph.*;
import ru.trader.analysis.*;
import ru.trader.analysis.graph.ConnectibleGraph;
import ru.trader.analysis.graph.Edge;
import java.util.*;
import java.util.stream.Collectors;
public class MarketAnalyzer {
private final static Logger LOG = LoggerFactory.getLogger(MarketAnalyzer.class);
private final Market market;
private final FilteredMarket market;
private final Profile profile;
private final RouteSearcher searcher;
private MarketAnalyzerCallBack callback;
private MarketFilter filter;
private double tank;
private double maxDistance;
private int segmentSize;
private int limit;
private int jumps;
private int cargo;
private final static Comparator<Order> orderComparator = (o1, o2) -> o2.compareTo(o1);
public MarketAnalyzer(Market market) {
this(market, new MarketAnalyzerCallBack());
public MarketAnalyzer(FilteredMarket market, Profile profile) {
this(market, profile, new MarketAnalyzerCallBack());
}
public MarketAnalyzer(Market market, MarketAnalyzerCallBack callback) {
public MarketAnalyzer(FilteredMarket market, Profile profile, MarketAnalyzerCallBack callback) {
this.market = market;
this.callback = callback;
this.limit = 100;
this.segmentSize = 0;
this.profile = profile;
this.searcher = new RouteSearcher(new Scorer(market, profile));
}
public void setCallback(MarketAnalyzerCallBack callback) {
this.callback = callback;
}
public void setFilter(MarketFilter filter) {
this.filter = filter;
}
public void setTank(double tank) {
this.tank = tank;
}
public void setMaxDistance(double maxDistance) {
this.maxDistance = maxDistance;
}
public void setJumps(int jumps) {
this.jumps = jumps;
}
public void setCargo(int cargo) {
this.cargo = cargo;
}
public void setSegmentSize(int segmentSize) {
this.segmentSize = segmentSize;
}
public void setPathsCount(int count) {
this.limit = count;
}
public Collection<Offer> getOffers(OFFER_TYPE offerType, Item item, MarketFilter filter){
Collection<Offer> offers = market.getOffers(offerType, item);
Collection<Offer> res = new ArrayList<>(offers.size());
callback.setMax(offers.size());
for (Offer offer : offers) {
if (callback.isCancel()) break;
if (isFiltered(offer.getVendor()) || filter.isFiltered(offer.getVendor())){
LOG.trace("Is filtered, skip");
callback.inc();
continue;
}
res.add(offer);
callback.inc();
}
callback.onEnd();
return res;
}
public Collection<Vendor> getVendors(MarketFilter filter){
Collection<Vendor> vendors = getVendors();
Collection<Vendor> res = new ArrayList<>(vendors.size());
callback.setMax(vendors.size());
for (Vendor vendor : vendors) {
if (callback.isCancel()) break;
if (filter.isFiltered(vendor)){
LOG.trace("Is filtered, skip");
callback.inc();
continue;
}
res.add(vendor);
callback.inc();
}
callback.onEnd();
return res;
}
public Collection<Order> getTop(double balance){
public Collection<Order> getTop(int limit){
LOG.debug("Get top {}", limit);
Collection<Place> places = getPlaces();
List<Order> top = new ArrayList<>(limit);
LimitedQueue<Order> top = new LimitedQueue<>(limit, orderComparator);
callback.setMax(places.size());
for (Place place : places) {
if (callback.isCancel()) break;
LOG.trace("Check place {}", place);
Collection<Order> orders = getOrders(place, balance, top.isEmpty() ? 0 : top.get(top.size()-1).getProfit());
TopList.addAllToTop(top, orders, limit, orderComparator);
Collection<Order> orders = getOrders(place, top.isEmpty() ? 0 : top.last().getProfit());
top.addAll(orders);
callback.inc();
}
callback.onEnd();
return top;
}
public Collection<Order> getOrders(Vendor vendor, double balance) {
Collection<Place> places = getPlaces();
Graph<Place> graph = new Graph<Place>(vendor.getPlace(), places, tank, maxDistance, true, jumps, Path::new, callback.onStartGraph());
return getOrders(graph, Collections.singleton(vendor), balance, 0);
public Collection<Order> getOrders(Place place) {
return getOrders(place, 0);
}
public Collection<Order> getOrders(Place place, double balance) {
return getOrders(place, balance, 0);
public Collection<Order> getOrders(Place from, Place to) {
if (isInaccessible(from, to)){
return Collections.emptyList();
}
return getOrders(getVendors(from), getVendors(to), 0);
}
private Collection<Order> getOrders(Place place, double balance, double lowProfit) {
Collection<Place> places = getPlaces();
Graph<Place> graph = new Graph<>(place, places, tank, maxDistance, true, jumps, Path::new, callback.onStartGraph());
return getOrders(graph, place.get(), balance, lowProfit);
public Collection<Order> getOrders(Place from, Vendor to) {
if (isInaccessible(from, to.getPlace())){
return Collections.emptyList();
}
return getOrders(getVendors(from), Collections.singleton(to), 0);
}
private Collection<Order> getOrders(Graph<Place> graph, Collection<Vendor> sellers, double balance, double lowProfit) {
public Collection<Order> getOrders(Vendor vendor) {
return getOrders(vendor.getPlace(), Collections.singleton(vendor), 0);
}
public Collection<Order> getOrders(Vendor from, Place to) {
if (isInaccessible(from.getPlace(), to)){
return Collections.emptyList();
}
return getOrders(Collections.singleton(from), to.get(), 0);
}
public Collection<Order> getOrders(Vendor from, Vendor to) {
if (isInaccessible(from.getPlace(), to.getPlace())){
return Collections.emptyList();
}
return getOrders(Collections.singleton(from), Collections.singleton(to), 0);
}
private Collection<Order> getOrders(Place place, double lowProfit) {
return getOrders(place, getVendors(place), lowProfit);
}
private Collection<Order> getOrders(Place place, Collection<Vendor> sellers, double lowProfit) {
ConnectibleGraph<Place> graph = new ConnectibleGraph<>(profile);
graph.build(place, getPlaces());
List<Order> res = new ArrayList<>(20);
callback.setMax(sellers.size());
for (Vendor vendor : sellers) {
if (callback.isCancel()) break;
if (isFiltered(vendor)){
LOG.trace("Is filtered, skip");
callback.inc();
continue;
}
for (Offer sell : vendor.getAllSellOffers()) {
if (callback.isCancel()) break;
LOG.trace("Sell offer {}", sell);
if (sell.getCount() == 0) continue;
long count = Order.getMaxCount(sell, balance, cargo);
long count = Order.getMaxCount(sell, profile.getBalance(), profile.getShip().getCargo());
LOG.trace("count = {}", count);
if (count == 0) continue;
Iterator<Offer> buyers = market.getStatBuy(sell.getItem()).getOffers().descendingIterator();
Iterator<Offer> buyers = market.getBuy(sell.getItem()).iterator();
while (buyers.hasNext()){
if (callback.isCancel()) break;
Offer buy = buyers.next();
if (isFiltered(buy.getVendor())){
LOG.trace("Is filtered, skip");
continue;
}
if (!graph.isAccessible(buy.getVendor().getPlace())){
LOG.trace("Is inaccessible buyer, skip");
continue;
@@ -177,28 +130,19 @@ public class MarketAnalyzer {
return res;
}
private Collection<Order> getOrders(Collection<Vendor> sellers, Collection<Vendor> buyers, double balance, double lowProfit) {
private Collection<Order> getOrders(Collection<Vendor> sellers, Collection<Vendor> buyers, double lowProfit) {
List<Order> res = new ArrayList<>();
callback.setMax(sellers.size());
for (Vendor seller : sellers) {
if (callback.isCancel()) break;
if (isFiltered(seller)){
LOG.trace("Is filtered, skip");
callback.inc();
continue;
}
for (Offer sell : seller.getAllSellOffers()) {
if (callback.isCancel()) break;
if (sell.getCount() == 0) continue;
long count = Order.getMaxCount(sell, balance, cargo);
long count = Order.getMaxCount(sell, profile.getBalance(), profile.getShip().getCargo());
LOG.trace("Sell offer {}, count = {}", sell, count);
if (count == 0) continue;
for (Vendor buyer : buyers) {
if (callback.isCancel()) break;
if (isFiltered(buyer)){
LOG.trace("Is filtered, skip");
continue;
}
Offer buy = buyer.getBuy(sell.getItem());
if (buy != null){
Order order = new Order(sell, buy, count);
@@ -217,197 +161,62 @@ public class MarketAnalyzer {
return res;
}
public Collection<Order> getOrders(Vendor from, Vendor to, double balance) {
Graph<Place> graph = new Graph<Place>(from.getPlace(), getPlaces(), tank, maxDistance, true, jumps, Path::new);
if (!graph.isAccessible(to.getPlace())){
LOG.trace("Is inaccessible buyer");
return Collections.emptyList();
}
return getOrders(Collections.singleton(from), Collections.singleton(to), balance, 0);
public Collection<List<Edge<Place>>> getPaths(Place from, Place to){
return searcher.getPaths(from, to, getPlaces());
}
public Collection<Order> getOrders(Place from, Place to, double balance) {
Graph<Place> graph = new Graph<Place>(from, getPlaces(), tank, maxDistance, true, jumps, Path::new);
if (!graph.isAccessible(to)){
LOG.trace("Is inaccessible buyer");
return Collections.emptyList();
}
return getOrders(from.get(), to.get(), balance, 0);
public List<Edge<Place>> getPath(Place from, Place to){
return searcher.getPath(from, to, getPlaces());
}
public Collection<Order> getOrders(Vendor from, Place to, double balance) {
Graph<Place> graph = new Graph<Place>(from.getPlace(), getPlaces(), tank, maxDistance, true, jumps, Path::new);
if (!graph.isAccessible(to)){
LOG.trace("Is inaccessible buyer");
return Collections.emptyList();
}
return getOrders(Collections.singleton(from), to.get(), balance, 0);
}
public Collection<Order> getOrders(Place from, Vendor to, double balance) {
Graph<Place> graph = new Graph<Place>(from, getPlaces(), tank, maxDistance, true, jumps, Path::new);
if (!graph.isAccessible(to.getPlace())){
LOG.trace("Is inaccessible buyer");
return Collections.emptyList();
}
return getOrders(from.get(), Collections.singleton(to), balance, 0);
}
public Collection<Path<Place>> getPaths(Place from, Place to){
Graph<Place> graph = new Graph<Place>(from, getPlaces(), tank, maxDistance, true, jumps, Path::new);
return graph.getPathsTo(to);
}
public Path<Place> getPath(Place from, Place to){
Graph<Place> graph = new Graph<Place>(from, getPlaces(), tank, maxDistance, true, jumps, Path::new);
return graph.getFastPathTo(to);
}
public PathRoute getPath(Vendor from, Vendor to){
RouteGraph graph = new RouteGraph(from, getVendors(true), tank, maxDistance, true, jumps);
return (PathRoute)graph.getFastPathTo(to);
}
public Collection<PathRoute> getPaths(Vendor from, double balance){
callback.setMax(1);
RouteSearcher searcher = new RouteSearcher(maxDistance, tank, segmentSize, callback.onStartSearch());
Collection<Vendor> vendors = getVendors(true);
Collection<PathRoute> res = searcher.getPaths(from, vendors, jumps, balance, cargo, limit);
callback.inc();
callback.onEndSearch();
return res;
}
public Collection<PathRoute> getPaths(Place from, double balance){
List<PathRoute> top = new ArrayList<>(limit);
Collection<Vendor> vendors = getVendors(true);
public Collection<Route> getTopRoutes(int limit){
LOG.debug("Get top {}", limit);
LimitedQueue<Route> top = new LimitedQueue<>(limit);
Collection<Vendor> vendors = getVendors();
callback.setMax(vendors.size());
RouteSearcher searcher = new RouteSearcher(maxDistance, tank, segmentSize, callback.onStartSearch());
for (Vendor vendor : from.get()) {
if (callback.isCancel()) break;
if (isFiltered(vendor)){
LOG.trace("Is filtered, skip");
callback.inc();
continue;
}
Collection<PathRoute> paths = searcher.getPaths(vendor, vendors, jumps, balance, cargo, limit);
TopList.addAllToTop(top, paths, limit, RouteGraph.byProfitComparator);
callback.inc();
}
callback.onEndSearch();
return top;
}
public Collection<PathRoute> getPaths(Vendor from, Vendor to, double balance){
callback.setMax(1);
RouteSearcher searcher = new RouteSearcher(maxDistance, tank, segmentSize, callback.onStartSearch());
Collection<PathRoute> res = searcher.getPaths(from, to, getVendors(true), jumps, balance, cargo, limit);
callback.inc();
callback.onEndSearch();
return res;
}
public Collection<PathRoute> getPaths(Place from, Place to, double balance){
List<PathRoute> top = new ArrayList<>(limit);
Collection<Vendor> vendors = getVendors(true);
Collection<Vendor> fVendors = from.get();
Collection<Vendor> toVendors = to.get();
int count = (int) Math.ceil(limit / fVendors.size());
callback.setMax(fVendors.size() * toVendors.size());
RouteSearcher searcher = new RouteSearcher(maxDistance, tank, segmentSize, callback.onStartSearch());
for (Vendor fromVendor : fVendors) {
if (callback.isCancel()) break;
if (isFiltered(fromVendor)){
LOG.trace("Is filtered, skip");
callback.inc();
continue;
}
for (Vendor toVendor : toVendors) {
if (callback.isCancel()) break;
if (isFiltered(toVendor)){
LOG.trace("Is filtered, skip");
callback.inc();
continue;
}
Collection<PathRoute> paths = searcher.getPaths(fromVendor, toVendor, vendors, jumps, balance, cargo, count);
TopList.addAllToTop(top, paths, limit, RouteGraph.byProfitComparator);
callback.inc();
}
}
callback.onEndSearch();
return top;
}
public Collection<PathRoute> getPaths(Vendor from, Place to, double balance){
List<PathRoute> top = new ArrayList<>(limit);
Collection<Vendor> vendors = getVendors(true);
Collection<Vendor> toVendors = to.get();
int count = (int) Math.ceil(limit / toVendors.size());
callback.setMax(toVendors.size());
RouteSearcher searcher = new RouteSearcher(maxDistance, tank, segmentSize, callback.onStartSearch());
for (Vendor toVendor : toVendors) {
if (callback.isCancel()) break;
if (isFiltered(toVendor)){
LOG.trace("Is filtered, skip");
callback.inc();
continue;
}
Collection<PathRoute> paths = searcher.getPaths(from, toVendor, vendors, jumps, balance, cargo, count);
TopList.addAllToTop(top, paths, limit, RouteGraph.byProfitComparator);
callback.inc();
}
callback.onEndSearch();
return top;
}
public Collection<PathRoute> getPaths(Place from, Vendor to, double balance){
List<PathRoute> top = new ArrayList<>(limit);
Collection<Vendor> vendors = getVendors(true);
Collection<Vendor> fVendors = from.get();
int count = (int) Math.ceil(limit / fVendors.size());
callback.setMax(fVendors.size());
RouteSearcher searcher = new RouteSearcher(maxDistance, tank, segmentSize, callback.onStartSearch());
for (Vendor fromVendor : fVendors) {
if (callback.isCancel()) break;
if (isFiltered(fromVendor)){
LOG.trace("Is filtered, skip");
callback.inc();
continue;
}
Collection<PathRoute> paths = searcher.getPaths(fromVendor, to, vendors, jumps, balance, cargo, count);
TopList.addAllToTop(top, paths, limit, RouteGraph.byProfitComparator);
callback.inc();
}
callback.onEndSearch();
return top;
}
public Collection<PathRoute> getTopPaths(double balance){
List<PathRoute> top = new ArrayList<>(limit);
Collection<Vendor> vendors = getVendors(true);
callback.setMax(vendors.size());
RouteSearcher searcher = new RouteSearcher(maxDistance, tank, segmentSize, callback.onStartSearch());
for (Vendor vendor : vendors) {
if (callback.isCancel()) break;
Collection<PathRoute> paths = searcher.getPaths(vendor, vendor, vendors, jumps, balance, cargo, 3);
TopList.addAllToTop(top, paths, limit, RouteGraph.byProfitComparator);
Collection<Route> paths = searcher.getRoutes(vendor, vendor, vendors, 3);
top.addAll(paths);
callback.inc();
}
callback.onEndSearch();
return top;
}
public PathRoute getPath(Collection<Vendor> vendors, double balance) {
PathRoute res = null;
public Collection<Route> getRoutes(Place from){
return searcher.getRoutes(getVendors(from), getVendors());
}
public Collection<Route> getRoutes(Place from, Place to){
return searcher.getRoutes(getVendors(from), getVendors(to), getVendors());
}
public Collection<Route> getRoutes(Place from, Vendor to){
return searcher.getRoutes(getVendors(from), Collections.singleton(to), getVendors());
}
public Collection<Route> getRoutes(Vendor from){
return searcher.getRoutes(from, getVendors());
}
public Collection<Route> getRoutes(Vendor from, Place to){
return searcher.getRoutes(Collections.singleton(from), getVendors(to), getVendors());
}
public Collection<Route> getRoutes(Vendor from, Vendor to){
return searcher.getRoutes(from, to, getVendors());
}
public Route getRoute(Collection<Vendor> vendors) {
Route res = null;
callback.setMax(vendors.size());
for (Vendor from : vendors) {
RouteSearcher searcher = new RouteSearcher(maxDistance, tank, segmentSize, callback.onStartSearch());
//TODO: implement search with constant length
Collection<PathRoute> paths = searcher.getPaths(from, vendors, jumps, balance, cargo, limit);
Optional<PathRoute> route = paths.stream().filter(p -> p.contains(vendors)).findFirst();
if (route.isPresent() && (res == null || RouteGraph.byProfitComparator.compare(res, route.get()) > 0)){
Collection<Route> paths = searcher.getRoutes(from, vendors);
Optional<Route> route = paths.stream().filter(p -> p.contains(vendors)).findFirst();
if (route.isPresent() && (res == null || res.compareTo(route.get()) > 0)){
res = route.get();
}
callback.inc();
@@ -416,32 +225,25 @@ public class MarketAnalyzer {
return res;
}
private Collection<Place> getPlaces(){
if (filter != null){
return filter.filtered(market.get());
} else {
return market.get();
private boolean isInaccessible(Place from, Place to){
ConnectibleGraph<Place> graph = new ConnectibleGraph<>(profile);
graph.build(from, getPlaces());
if (!graph.isAccessible(to)){
LOG.trace("Is inaccessible buyer");
return true;
}
return false;
}
private Collection<Vendor> getVendors(){
return getVendors(false);
private List<Place> getPlaces(){
return market.get().collect(Collectors.toList());
}
private Collection<Vendor> getVendors(boolean includeTransit){
if (filter != null){
Collection<Vendor> vendors = new PlacesWrapper(getPlaces(), includeTransit);
return filter.filteredVendors(vendors);
} else {
return market.getVendors(includeTransit);
}
private List<Vendor> getVendors(){
return market.getMarkets(true).collect(Collectors.toList());
}
public MarketFilter getFilter() {
return filter;
}
private boolean isFiltered(Vendor vendor){
return filter != null && (filter.isFiltered(vendor.getPlace()) || filter.isFiltered(vendor));
private List<Vendor> getVendors(Place place){
return market.getVendors(place).collect(Collectors.toList());
}
}

View File

@@ -7,7 +7,6 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.EnumSet;
import java.util.Properties;
import java.util.stream.Collectors;
public class MarketFilter {
private final static Logger LOG = LoggerFactory.getLogger(MarketFilter.class);
@@ -97,15 +96,6 @@ public class MarketFilter {
return false;
}
public Collection<Place> filtered(Collection<Place> places){
return places.parallelStream().filter(p -> !isFiltered(p)).collect(Collectors.toList());
}
public Collection<Vendor> filteredVendors(Collection<Vendor> vendors){
return vendors.parallelStream().filter(v -> !isFiltered(v)).collect(Collectors.toList());
}
public static MarketFilter buildFilter(Properties values, Market market){
MarketFilter filter = new MarketFilter();
String v = values.getProperty("filter.center", null);

View File

@@ -22,6 +22,7 @@ public class Profile {
refill = true;
jumps = 6;
lands = 4;
routesCount = 30;
scoreOrdersCount = 5;
distanceMult = 0.8;
landMult = 0.95;

View File

@@ -7,29 +7,32 @@ import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ru.trader.TestUtil;
import ru.trader.graph.Path;
import ru.trader.analysis.FilteredMarket;
import ru.trader.analysis.graph.Edge;
import ru.trader.analysis.graph.PPath;
import ru.trader.store.simple.*;
import java.util.Collection;
import java.util.List;
public class MarketAnalyzerTest extends Assert {
private final static Logger LOG = LoggerFactory.getLogger(MarketAnalyzerTest.class);
private static Market market = new SimpleMarket();
private static Place v1;
private static Place v2;
private static Place v3;
private static Place v4;
private static Place v5;
private static Place v6;
private static Place v7;
private static Place v8;
private static Place v9;
private static Place v10;
private static Place v11;
private static Item ITEM1 = new SimpleItem("ITEM1");
private static Item ITEM2 = new SimpleItem("ITEM2");
private static Item ITEM3 = new SimpleItem("ITEM3");
private FilteredMarket market;
private Place v1;
private Place v2;
private Place v3;
private Place v4;
private Place v5;
private Place v6;
private Place v7;
private Place v8;
private Place v9;
private Place v10;
private Place v11;
private Item ITEM1 = new SimpleItem("ITEM1");
private Item ITEM2 = new SimpleItem("ITEM2");
private Item ITEM3 = new SimpleItem("ITEM3");
private void add(Place place, Offer offer){
if (place.isEmpty()){
@@ -41,6 +44,8 @@ public class MarketAnalyzerTest extends Assert {
@Before
public void setUp() throws Exception {
Market market = new SimpleMarket();
v1 = new SimplePlace("v1_x0y0z0",0,0,0);
v2 = new SimplePlace("v2_x1y0z0",1,0,0);
v3 = new SimplePlace("v3_x0y1z0",0,1,0);
@@ -80,29 +85,34 @@ public class MarketAnalyzerTest extends Assert {
add(v10, new SimpleOffer(OFFER_TYPE.BUY, ITEM3, 140, 1));
add(v11, new SimpleOffer(OFFER_TYPE.BUY, ITEM3, 500, 1));
MarketFilter filter = new MarketFilter();
this.market = new FilteredMarket(market, filter);
}
@Test
public void testPaths() throws Exception {
LOG.info("Start paths test");
MarketAnalyzer analyzer = new MarketAnalyzer(market);
analyzer.setJumps(5);analyzer.setMaxDistance(1);analyzer.setTank(1);
// maxDist - 1, fulltank - 1
Ship ship = new Ship();
ship.setMass(340);ship.setTank(0.6);
Profile profile = new Profile(ship);
profile.setJumps(5);
MarketAnalyzer analyzer = new MarketAnalyzer(market, profile);
Collection<Path<Place>> paths = analyzer.getPaths(v1, v2);
TestUtil.assertCollectionEquals(paths, Path.toPath(v1, v2));
Collection<List<Edge<Place>>> paths = analyzer.getPaths(v1, v2);
TestUtil.assertPaths(paths, PPath.of(v1, v2));
paths = analyzer.getPaths(v1, v3);
TestUtil.assertCollectionEquals(paths, Path.toPath(v1, v3));
TestUtil.assertPaths(paths, PPath.of(v1, v3));
paths = analyzer.getPaths(v1, v4);
TestUtil.assertCollectionEquals(paths, Path.toPath(v1, v4));
TestUtil.assertPaths(paths, PPath.of(v1, v4));
paths = analyzer.getPaths(v1, v5);
assertTrue(paths.isEmpty());
paths = analyzer.getPaths(v2, v5);
TestUtil.assertCollectionEquals(paths, Path.toPath(v2, v5));
TestUtil.assertPaths(paths, PPath.of(v2, v5));
paths = analyzer.getPaths(v4, v3);
assertTrue(paths.isEmpty());
@@ -111,80 +121,95 @@ public class MarketAnalyzerTest extends Assert {
@Test
public void testPathsWithStock() throws Exception {
LOG.info("Start paths with stock test");
MarketAnalyzer analyzer = new MarketAnalyzer(market);
analyzer.setJumps(5);analyzer.setMaxDistance(1);analyzer.setTank(2);
// jumpRange - 1, fulltank - 2
Ship ship = new Ship();
ship.setMass(340);ship.setTank(1.17);
Profile profile = new Profile(ship);
profile.setJumps(5);
MarketAnalyzer analyzer = new MarketAnalyzer(market, profile);
Collection<Path<Place>> paths = analyzer.getPaths(v1, v2);
TestUtil.assertCollectionContainAll(paths, Path.toPath(v1, v2));
Collection<List<Edge<Place>>> paths = analyzer.getPaths(v1, v2);
TestUtil.assertPaths(paths, PPath.of(v1, v2));
paths = analyzer.getPaths(v1, v3);
TestUtil.assertCollectionContainAll(paths, Path.toPath(v1, v3));
TestUtil.assertPaths(paths, PPath.of(v1, v3));
paths = analyzer.getPaths(v1, v4);
TestUtil.assertCollectionContainAll(paths, Path.toPath(v1, v4));
TestUtil.assertPaths(paths, PPath.of(v1, v4));
paths = analyzer.getPaths(v1, v5);
TestUtil.assertCollectionContainAll(paths, Path.toPath(v1, v2, v5), Path.toPath(v1, v3, v5));
TestUtil.assertPaths(paths, PPath.of(v1, v2, v5), PPath.of(v1, v3, v5));
paths = analyzer.getPaths(v2, v5);
TestUtil.assertCollectionContainAll(paths, Path.toPath(v2, v5));
TestUtil.assertPaths(paths, PPath.of(v2, v5));
paths = analyzer.getPaths(v4, v3);
TestUtil.assertCollectionContainAll(paths, Path.toPath(v4, v1, v3));
TestUtil.assertPaths(paths, PPath.of(v4, v1, v3));
}
@Test
public void testPathsWithStockAndRefill() throws Exception {
LOG.info("Start paths with stock and refill test");
MarketAnalyzer analyzer = new MarketAnalyzer(market);
analyzer.setJumps(2);analyzer.setMaxDistance(10);analyzer.setTank(15);
// jumpRange - 10, fulltank - 15
Ship ship = new Ship();
ship.setMass(30);ship.setTank(0.7);
Profile profile = new Profile(ship);
profile.setJumps(2);
MarketAnalyzer analyzer = new MarketAnalyzer(market, profile);
Collection<Path<Place>> paths = analyzer.getPaths(v10, v6);
TestUtil.assertCollectionContainAll(paths, Path.toPath(v10, v6), Path.toPath(v10, v11, v6),
Path.toPath(v10, v8, v6));
Collection<List<Edge<Place>>> paths = analyzer.getPaths(v10, v6);
TestUtil.assertPaths(paths, PPath.of(v10, v6), PPath.of(v10, v11, v6),
PPath.of(v10, v8, v6));
paths = analyzer.getPaths(v1, v3);
TestUtil.assertCollectionContainAll(paths, Path.toPath(v1, v3), Path.toPath(v1, v2, v3),
Path.toPath(v1, v4, v3), Path.toPath(v1, v5, v3)
TestUtil.assertPaths(paths, PPath.of(v1, v3), PPath.of(v1, v2, v3),
PPath.of(v1, v4, v3), PPath.of(v1, v5, v3)
);
}
@Test
public void testPathsWithStockAndRefill2() throws Exception {
LOG.info("Start paths with stock and refill test 2");
MarketAnalyzer analyzer = new MarketAnalyzer(market);
analyzer.setJumps(3);analyzer.setMaxDistance(10);analyzer.setTank(15);
// jumpRange - 10, fulltank - 15
Ship ship = new Ship();
ship.setMass(30);ship.setTank(0.7);
Profile profile = new Profile(ship);
profile.setJumps(3);
MarketAnalyzer analyzer = new MarketAnalyzer(market, profile);
Collection<Path<Place>> paths = analyzer.getPaths(v10, v6);
TestUtil.assertCollectionContainAll(paths, Path.toPath(v10, v6), Path.toPath(v10, v11, v6), Path.toPath(v10, v11, v10, v6),
Path.toPath(v10, v8, v6), Path.toPath(v10, v8, v10, v6), Path.toPath(v10, v8, v11, v6));
Collection<List<Edge<Place>>> paths = analyzer.getPaths(v10, v6);
TestUtil.assertPaths(paths, PPath.of(v10, v6), PPath.of(v10, v8, v6), PPath.of(v10, v11, v6),
PPath.of(v10, v8, v11, v6), PPath.of(v10, v8, v10, v6), PPath.of(v10, v11, v10, v6),
PPath.of(v10, v6, v7, v6), PPath.of(v10, v6, v8, v6), PPath.of(v10, v6, v11, v6),
PPath.of(v10, v6, v10, v6));
paths = analyzer.getPaths(v10, v7);
TestUtil.assertCollectionContainAll(paths, Path.toPath(v10, v6, v7), Path.toPath(v10, v11, v6, v7),
Path.toPath(v10, v8, v6, v7)
TestUtil.assertPaths(paths, PPath.of(v10, v6, v7), PPath.of(v10, v11, v6, v7),
PPath.of(v10, v8, v6, v7)
);
paths = analyzer.getPaths(v10, v8);
TestUtil.assertCollectionContainAll(paths, Path.toPath(v10, v8), Path.toPath(v10, v11, v8),
Path.toPath(v10, v11, v6, v8), Path.toPath(v10, v6, v8), Path.toPath(v10, v6, v11, v8),
Path.toPath(v10, v11, v10, v8), Path.toPath(v10, v6, v10, v8));
TestUtil.assertPaths(paths, PPath.of(v10, v8), PPath.of(v10, v11, v8), PPath.of(v10, v6, v8),
PPath.of(v10, v8, v11, v8), PPath.of(v10, v8, v10, v8), PPath.of(v10, v8, v6, v8),
PPath.of(v10, v11, v10, v8), PPath.of(v10, v11, v6, v8), PPath.of(v10, v6, v11, v8),
PPath.of(v10, v6, v10, v8));
paths = analyzer.getPaths(v10, v9);
assertTrue(paths.isEmpty());
paths = analyzer.getPaths(v10, v10);
TestUtil.assertCollectionContainAll(paths, Path.toPath(v10, v11, v10), Path.toPath(v10, v6, v10),
Path.toPath(v10, v11, v6, v10), Path.toPath(v10, v6, v11, v10),
Path.toPath(v10, v8, v10), Path.toPath(v10, v8, v11, v10),
Path.toPath(v10, v8, v6, v10), Path.toPath(v10, v8, v6, v10));
TestUtil.assertPaths(paths, PPath.of(v10, v11, v10), PPath.of(v10, v6, v10),
PPath.of(v10, v11, v6, v10), PPath.of(v10, v6, v11, v10),
PPath.of(v10, v8, v10), PPath.of(v10, v8, v11, v10),
PPath.of(v10, v8, v6, v10), PPath.of(v10, v8, v6, v10));
}
@After
public void tearDown() throws Exception {
market = new SimpleMarket();
market = null;
}
}

View File

@@ -4,7 +4,7 @@ import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import ru.trader.TestUtil;
import ru.trader.graph.PathRoute;
import ru.trader.analysis.*;
import ru.trader.store.simple.Store;
import java.io.InputStream;
import java.util.Collection;
@@ -16,25 +16,40 @@ public class MarketAnalyzerTest2 extends Assert {
public void testRoutes() throws Exception {
InputStream is = getClass().getResourceAsStream("/world.xml");
Market market = Store.loadFromFile(is);
MarketAnalyzer analyzer = new MarketAnalyzer(market);
MarketFilter filter = new MarketFilter();
FilteredMarket fWorld = new FilteredMarket(market, filter);
// Balance: 6000000, cargo: 440, tank: 40, distance: 13.4, jumps: 6
// Ithaca (Palladium to LHS 3262) -> Morgor -> LHS 3006 -> LHS 3262 (Consumer Technology to Ithaca) -> LHS 3006 -> Morgor -> Ithaca
// Profit: 981200, avg: 490600, distance: 67.5, lands: 2
Vendor ithaca = market.get().stream().filter((v)->v.getName().equals("Ithaca")).findFirst().get().get().iterator().next();
Vendor morgor = market.get().stream().filter((v)->v.getName().equals("Morgor")).findFirst().get().get().iterator().next();
Vendor lhs3006 = market.get().stream().filter((v)->v.getName().equals("LHS 3006")).findFirst().get().get().iterator().next();
Vendor lhs3262 = market.get().stream().filter((v)->v.getName().equals("LHS 3262")).findFirst().get().get().iterator().next();
analyzer.setCargo(440);analyzer.setTank(40);analyzer.setMaxDistance(13.4);analyzer.setJumps(6);
Collection<PathRoute> paths = analyzer.getPaths(ithaca, ithaca, 6000000);
PathRoute expect = PathRoute.toPathRoute(ithaca, morgor, lhs3006, lhs3262, lhs3006, morgor, ithaca);
Optional<PathRoute> path = paths.stream().filter((p)->p.equals(expect)).findFirst();
Ship ship = new Ship();
ship.setCargo(440); ship.setTank(15);
ship.setEngine(5, 'A'); ship.setMass(466);
Profile profile = new Profile(ship);
profile.setBalance(6000000); profile.setJumps(6);
profile.setRoutesCount(100);
MarketAnalyzer analyzer = new MarketAnalyzer(fWorld, profile);
Vendor ithaca = market.get("Ithaca").get().iterator().next();
Vendor morgor = market.get("Morgor").asTransit();
Vendor lhs3006 = market.get("LHS 3006").asTransit();
Vendor lhs3262 = market.get("LHS 3262").get().iterator().next();
Collection<Route> paths = analyzer.getRoutes(ithaca, ithaca);
Route expect = new Route(new RouteEntry(ithaca, false, 3.3789702637348586d, 0));
expect.add(new RouteEntry(morgor, false, 4.137765020523591d, 0));
expect.add(new RouteEntry(lhs3006, false, 4.0674474942172765d, 0));
expect.add(new RouteEntry(lhs3262, true, 4.149937831634785d, 0));
expect.add(new RouteEntry(lhs3006, false, 4.1292528548103d, 0));
expect.add(new RouteEntry(morgor, false, 3.3050364899848566, 0));
expect.add(new RouteEntry(ithaca, false, 0, 0));
RouteFiller filler = new RouteFiller(new Scorer(fWorld, profile));
filler.fill(expect);
Optional<Route> path = paths.stream().findFirst();
assertTrue(path.isPresent());
PathRoute actual = path.get().getRoot();
TestUtil.assertCollectionContain(paths, expect);
Route actual = path.get();
assertEquals(expect, actual);
assertEquals(981200, actual.getProfit(), 0.00001);
assertEquals(72.42, actual.getDistance(), 0.01);
assertEquals(2, actual.getLandsCount());
assertEquals(490600, actual.getAvgProfit() , 0.00001);
assertEquals(2, actual.getLands());
}
//test best avg profit
@@ -42,27 +57,51 @@ public class MarketAnalyzerTest2 extends Assert {
public void testRoutes2() throws Exception {
InputStream is = getClass().getResourceAsStream("/test2.xml");
Market market = Store.loadFromFile(is);
MarketAnalyzer analyzer = new MarketAnalyzer(market);
MarketFilter filter = new MarketFilter();
FilteredMarket fWorld = new FilteredMarket(market, filter);
// Balance: 6000000, cargo: 104 tank: 150, distance: 12.6, jumps: 4
// LHS 21 (Resonatic Separator to Sui Xing) -> Bonde -> Sui Xing (Palladium to LHS 21) -> Bonde -> LHS 21
// Profit: 981200, avg: 490600, distance: 67.5, lands: 2
Place lhs21 = market.get().stream().filter((v)->v.getName().equals("LHS 21")).findFirst().get();
Place suiXing = market.get().stream().filter((v)->v.getName().equals("Sui Xing")).findFirst().get();
analyzer.setCargo(104);analyzer.setTank(150);analyzer.setMaxDistance(12.6);analyzer.setJumps(4);analyzer.setPathsCount(100);
Collection<PathRoute> paths = analyzer.getPaths(lhs21, lhs21, 6000000);
Optional<PathRoute> path = paths.stream().findFirst();
// LHS 21 -> Bonde -> LHS 21
// Profit: 114816, distance: 8.16, lands: 2
Ship ship = new Ship();
ship.setCargo(104); ship.setTank(150);
ship.setEngine(5, 'A'); ship.setMass(865);
Profile profile = new Profile(ship);
profile.setBalance(6000000); profile.setJumps(4);
profile.setRoutesCount(100);
MarketAnalyzer analyzer = new MarketAnalyzer(fWorld, profile);
Place lhs21 = market.get("LHS 21");
Place bonde = market.get("Bonde");
Place suiXing = market.get("Sui Xing");
Collection<Route> paths = analyzer.getRoutes(lhs21, lhs21);
Optional<Route> path = paths.stream().findFirst();
assertTrue(path.isPresent());
PathRoute actual = path.get().getRoot();
Route actual = path.get();
assertEquals(114816, actual.getProfit(), 0.00001);
assertEquals(8.16, actual.getDistance(), 0.01);
assertEquals(2, actual.getLands());
Place aPlace = actual.get(0).getVendor().getPlace();
assertEquals(lhs21, aPlace);
aPlace = actual.get(1).getVendor().getPlace();
assertEquals(bonde, aPlace);
// If distance to station has small mult
// LHS 21 (Resonatic Separator to Sui Xing) -> Bonde -> Sui Xing (Palladium to LHS 21) -> Bonde -> LHS 21
// Profit: 199056, distance: 28.72, lands: 2
profile.setDistanceMult(0.1);
paths = analyzer.getRoutes(lhs21, lhs21);
path = paths.stream().findFirst();
assertTrue(path.isPresent());
actual = path.get();
assertEquals(199056, actual.getProfit(), 0.00001);
assertEquals(28.72, actual.getDistance(), 0.01);
assertEquals(2, actual.getLandsCount());
assertEquals(99528, actual.getAvgProfit() , 0.00001);
assertEquals(2, actual.getLands());
Place aPlace = actual.get().getPlace();
aPlace = actual.get(0).getVendor().getPlace();
assertEquals(lhs21, aPlace);
actual = actual.getNext().getNext();
aPlace = actual.get().getPlace();
aPlace = actual.get(2).getVendor().getPlace();
assertEquals(suiXing, aPlace);
}