diff --git a/core/src/main/java/ru/trader/analysis/CrawlerSpecificator.java b/core/src/main/java/ru/trader/analysis/CrawlerSpecificator.java new file mode 100644 index 0000000..db55a15 --- /dev/null +++ b/core/src/main/java/ru/trader/analysis/CrawlerSpecificator.java @@ -0,0 +1,107 @@ +package ru.trader.analysis; + +import ru.trader.analysis.graph.Edge; +import ru.trader.core.Offer; +import ru.trader.core.Vendor; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.function.Consumer; + +public class CrawlerSpecificator { + private final List any; + private final List containsAny; + private final List all; + private final Collection offers; + private boolean byTime; + + public CrawlerSpecificator() { + any = new ArrayList<>(); + all = new ArrayList<>(); + containsAny = new ArrayList<>(); + offers = new ArrayList<>(); + byTime = false; + } + + public void setByTime(boolean byTime){ + this.byTime = byTime; + } + + public void all(Collection vendors){ + all.addAll(vendors); + } + + public void any(Collection vendors){ + containsAny.addAll(vendors); + } + + public void target(Vendor vendor){ + any.add(vendor); + } + + public void targetAny(Collection vendors){ + any.addAll(vendors); + } + + public void add(Vendor vendor, boolean required){ + if (required){ + all.add(vendor); + } else { + any.add(vendor); + } + } + + public void remove(Vendor vendor, boolean required){ + if (required){ + all.remove(vendor); + } else { + any.remove(vendor); + } + } + + public void buy(Collection offers){ + this.offers.addAll(offers); + } + + public CrawlerSpecification build(Consumer>> onFoundFunc, RouteSpecification andSpec){ + RouteSpecification spec; + RouteSpecification res = null; + if (!all.isEmpty()){ + spec = all.size() > 1 ? RouteSpecificationByTargets.all(all) : new RouteSpecificationByTarget<>(all.get(0)); + res = spec; + } + if (!any.isEmpty()){ + spec = any.size() > 1 ? RouteSpecificationByTargets.any(any) : new RouteSpecificationByTarget<>(any.get(0)); + if (res != null){ + res.and(spec); + } else { + res = spec; + } + } + if (!containsAny.isEmpty()){ + spec = RouteSpecificationByTargets.containAny(containsAny); + if (res != null){ + res.and(spec); + } else { + res = spec; + } + } + if (andSpec != null){ + if (res != null){ + res.and(andSpec); + } else { + res = andSpec; + } + } + if (byTime){ + return new CrawlerSpecificationByTime(res, onFoundFunc); + } + return new CrawlerSpecificationByProfit(res, onFoundFunc); + } + + public CrawlerSpecification build(Consumer>> onFoundFunc){ + return build(onFoundFunc, null); + } + +} diff --git a/core/src/main/java/ru/trader/analysis/RouteSearcher.java b/core/src/main/java/ru/trader/analysis/RouteSearcher.java index 5b9462e..98f0120 100644 --- a/core/src/main/java/ru/trader/analysis/RouteSearcher.java +++ b/core/src/main/java/ru/trader/analysis/RouteSearcher.java @@ -66,16 +66,19 @@ public class RouteSearcher { public List getRoutes(Collection fVendors, Collection toVendors, Collection vendors){ List res = new LimitedQueue<>(scorer.getProfile().getRoutesCount()); int count = (int) Math.ceil(scorer.getProfile().getRoutesCount() / fVendors.size()); - RouteSpecification specification = RouteSpecificationByTargets.any(toVendors); + CrawlerSpecificator specificator = new CrawlerSpecificator(); + specificator.any(toVendors); for (Vendor fromVendor : fVendors) { - Collection routes = search(fromVendor, fromVendor, vendors, count, specification); + Collection routes = search(fromVendor, fromVendor, vendors, count, specificator); res.addAll(routes); } return res; } public List getRoutes(Vendor from, Collection vendors){ - return search(from, from, vendors, scorer.getProfile().getRoutesCount(), RouteSpecificationByTargets.any(vendors)); + CrawlerSpecificator specificator = new CrawlerSpecificator(); + specificator.any(vendors); + return search(from, from, vendors, scorer.getProfile().getRoutesCount(), specificator); } public List getRoutes(Vendor from, Vendor to, Collection vendors){ @@ -83,24 +86,41 @@ public class RouteSearcher { } public List getRoutes(Vendor source, Vendor target, Collection vendors, int count){ - return search(source, target, vendors, count, null); + return search(source, target, vendors, count, new CrawlerSpecificator()); } - private List search(Vendor source, Vendor target, Collection vendors, int count, RouteSpecification specification){ + + public List getLoops(Vendor source, Collection vendors, int count){ + return searchLoops(source, vendors, count, new CrawlerSpecificator()); + } + + public List search(Vendor source, Vendor target, Collection vendors, int count, CrawlerSpecificator specificator){ LOG.trace("Start search route from {} to {}", source, target); VendorsGraph vGraph = new VendorsGraph(scorer, callback); LOG.trace("Build vendors graph"); vGraph.build(source, vendors); LOG.trace("Graph is builds"); RouteCollector collector = new RouteCollector(); - Crawler crawler = specification != null ? vGraph.crawler(specification, collector::add, callback) : vGraph.crawler(collector::add, callback); + Crawler crawler = vGraph.crawler(specificator.build(collector::add), callback); crawler.setMaxSize(scorer.getProfile().getLands()); crawler.findMin(target, count); return collector.get(); } - public List getLoops(Vendor source, Collection vendors, int count){ - return search(source, source, vendors, count, new LoopRouteSpecification(true)); + public List searchLoops(Vendor source, Collection vendors, int count, CrawlerSpecificator specificator){ + LOG.trace("Start search loops from {}", source); + VendorsGraph vGraph = new VendorsGraph(scorer, callback); + LOG.trace("Build vendors graph"); + vGraph.build(source, vendors); + LOG.trace("Graph is builds"); + RouteCollector collector = new RouteCollector(); + Crawler crawler = vGraph.crawler(specificator.build(collector::add, new LoopRouteSpecification<>(true)), callback); + crawler.setMaxSize(scorer.getProfile().getLands()); + crawler.findMin(source, count); + crawler = vGraph.crawler(specificator.build(collector::add, new RouteSpecificationByTarget<>(source)), callback); + crawler.setMaxSize(scorer.getProfile().getLands()); + crawler.findMin(source, 1); + return collector.get(); } private class RouteCollector {