implement limit by time for crawler specification
This commit is contained in:
@@ -6,26 +6,76 @@ import ru.trader.core.Vendor;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class CrawlerSpecificator {
|
||||
private final Set<Vendor> any;
|
||||
private final Set<Vendor> containsAny;
|
||||
private final Set<Vendor> all;
|
||||
private final Collection<Offer> offers;
|
||||
private final Collection<TimeEntry<Vendor>> any;
|
||||
private final Collection<TimeEntry<Vendor>> containsAny;
|
||||
private final Collection<TimeEntry<Vendor>> all;
|
||||
private final Collection<TimeEntry<Offer>> offers;
|
||||
private int groupCount;
|
||||
private boolean byTime;
|
||||
private boolean fullScan;
|
||||
|
||||
public CrawlerSpecificator() {
|
||||
any = new HashSet<>();
|
||||
all = new HashSet<>();
|
||||
containsAny = new HashSet<>();
|
||||
any = new ArrayList<>();
|
||||
all = new ArrayList<>();
|
||||
containsAny = new ArrayList<>();
|
||||
offers = new ArrayList<>();
|
||||
byTime = false;
|
||||
fullScan = true;
|
||||
}
|
||||
|
||||
private <T> void add(Collection<TimeEntry<T>> set, T obj){
|
||||
add(set, INFINITY_TIME, obj);
|
||||
}
|
||||
|
||||
private <T> void add(Collection<TimeEntry<T>> set, Long time, T obj){
|
||||
TimeEntry<T> entry = new TimeEntry<>(obj, time);
|
||||
boolean add = true;
|
||||
for (Iterator<TimeEntry<T>> iterator = set.iterator(); iterator.hasNext(); ) {
|
||||
TimeEntry<T> e = iterator.next();
|
||||
if (entry.obj.equals(e.obj)){
|
||||
if (entry.compareTo(e) >= 0){
|
||||
add = false;
|
||||
} else {
|
||||
iterator.remove();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (add){
|
||||
set.add(entry);
|
||||
}
|
||||
}
|
||||
|
||||
private <T> void addAll(Collection<TimeEntry<T>> set, Collection<T> objs){
|
||||
addAll(set, INFINITY_TIME, objs);
|
||||
}
|
||||
|
||||
private <T> void addAll(Collection<TimeEntry<T>> set, Long time, Collection<T> objs){
|
||||
for (T obj : objs) {
|
||||
add(set, time, obj);
|
||||
}
|
||||
}
|
||||
|
||||
private <T> boolean contains(Collection<TimeEntry<T>> set, T obj){
|
||||
for (TimeEntry<T> entry : set) {
|
||||
if (entry.obj.equals(obj)){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private <T> Map<Long, List<T>> groupByTime(Collection<TimeEntry<T>> set){
|
||||
return set.stream().collect(
|
||||
Collectors.groupingBy(TimeEntry::getTime,
|
||||
Collectors.mapping((Function<TimeEntry<T>, T>)TimeEntry::getObj, Collectors.toList())));
|
||||
}
|
||||
|
||||
|
||||
public void setByTime(boolean byTime){
|
||||
this.byTime = byTime;
|
||||
}
|
||||
@@ -39,43 +89,67 @@ public class CrawlerSpecificator {
|
||||
}
|
||||
|
||||
public void all(Collection<Vendor> vendors){
|
||||
all.addAll(vendors);
|
||||
addAll(all, vendors);
|
||||
}
|
||||
|
||||
public void all(Collection<Vendor> vendors, long time){
|
||||
addAll(all, time, vendors);
|
||||
}
|
||||
|
||||
public void any(Collection<Vendor> vendors){
|
||||
containsAny.addAll(vendors);
|
||||
addAll(containsAny, vendors);
|
||||
}
|
||||
|
||||
public void any(Collection<Vendor> vendors, long time){
|
||||
addAll(containsAny, time, vendors);
|
||||
}
|
||||
|
||||
public void target(Vendor vendor){
|
||||
any.add(vendor);
|
||||
add(any, vendor);
|
||||
}
|
||||
|
||||
public void target(Vendor vendor, long time){
|
||||
add(any, time, vendor);
|
||||
}
|
||||
|
||||
public void targetAny(Collection<Vendor> vendors){
|
||||
any.addAll(vendors);
|
||||
addAll(any, vendors);
|
||||
}
|
||||
|
||||
public void targetAny(Collection<Vendor> vendors, long time){
|
||||
addAll(any, time, vendors);
|
||||
}
|
||||
|
||||
public void add(Vendor vendor, boolean required){
|
||||
if (required){
|
||||
all.add(vendor);
|
||||
add(all, vendor);
|
||||
} else {
|
||||
any.add(vendor);
|
||||
add(any, vendor);
|
||||
}
|
||||
}
|
||||
|
||||
public void remove(Vendor vendor, boolean required){
|
||||
public void add(Vendor vendor, long time, boolean required){
|
||||
if (required){
|
||||
all.remove(vendor);
|
||||
add(all, time, vendor);
|
||||
} else {
|
||||
any.remove(vendor);
|
||||
add(any, time, vendor);
|
||||
}
|
||||
}
|
||||
|
||||
public void buy(Offer offer){
|
||||
offers.add(offer);
|
||||
add(offers, offer);
|
||||
}
|
||||
|
||||
public void buy(Offer offer, long time){
|
||||
add(offers, time, offer);
|
||||
}
|
||||
|
||||
public void buy(Collection<Offer> offers){
|
||||
this.offers.addAll(offers);
|
||||
addAll(this.offers, offers);
|
||||
}
|
||||
|
||||
public void buy(Collection<Offer> offers, long time){
|
||||
addAll(this.offers, time, offers);
|
||||
}
|
||||
|
||||
public void setGroupCount(int groupCount) {
|
||||
@@ -83,13 +157,14 @@ public class CrawlerSpecificator {
|
||||
}
|
||||
|
||||
public int getMinHop(){
|
||||
return all.size() + (any.isEmpty() ? 0 : 1) + (containsAny.isEmpty() ? 0 : 1) + offers.size()/4 ;
|
||||
return all.size() + (any.isEmpty() ? 0 : 1) + (containsAny.isEmpty() ? 0 : 1) + offers.size();
|
||||
}
|
||||
|
||||
public boolean contains(Vendor vendor){
|
||||
boolean res = all.contains(vendor) || any.contains(vendor) || containsAny.contains(vendor);
|
||||
boolean res = contains(all, vendor) || contains(any, vendor) || contains(containsAny, vendor);
|
||||
if (res) return true;
|
||||
for (Offer offer : offers) {
|
||||
for (TimeEntry<Offer> entry : offers){
|
||||
Offer offer = entry.obj;
|
||||
Offer sell = vendor.getSell(offer.getItem());
|
||||
res = sell != null && sell.getCount() >= offer.getCount();
|
||||
if (res) return true;
|
||||
@@ -98,24 +173,29 @@ public class CrawlerSpecificator {
|
||||
}
|
||||
|
||||
public Collection<Vendor> getVendors(Collection<Vendor> vendors){
|
||||
Set<Vendor> v = new HashSet<>(containsAny);
|
||||
v.addAll(any);
|
||||
v.addAll(all);
|
||||
Set<Vendor> v = containsAny.stream().map(e -> e.obj).collect(Collectors.toSet());
|
||||
any.stream().map(e -> e.obj).forEach(v::add);
|
||||
all.stream().map(e -> e.obj).forEach(v::add);
|
||||
offers.stream().map(e -> e.obj.getVendor()).forEach(v::add);
|
||||
v.addAll(vendors);
|
||||
return v;
|
||||
}
|
||||
|
||||
private RouteSpecification<Vendor> buildOffersSpec(Collection<Vendor> vendors){
|
||||
RouteSpecification<Vendor> res = null;
|
||||
for (Offer offer : offers) {
|
||||
for (TimeEntry<Offer> entry : offers) {
|
||||
Offer offer = entry.obj;
|
||||
List<Vendor> sellers = vendors.stream().filter(v -> {
|
||||
Offer sell = v.getSell(offer.getItem());
|
||||
return sell != null && sell.getCount() >= offer.getCount();
|
||||
}).collect(Collectors.toList());
|
||||
RouteSpecificationByPair<Vendor> spec = entry.time.equals(INFINITY_TIME) ?
|
||||
new RouteSpecificationByPair<>(sellers, offer.getVendor()) :
|
||||
new RouteSpecificationByPair<>(sellers, offer.getVendor(), entry.time);
|
||||
if (res != null){
|
||||
res = res.and(new RouteSpecificationByPair<>(sellers, offer.getVendor()));
|
||||
res = res.and(spec);
|
||||
} else {
|
||||
res = new RouteSpecificationByPair<>(sellers, offer.getVendor());
|
||||
res = spec;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
@@ -125,23 +205,51 @@ public class CrawlerSpecificator {
|
||||
RouteSpecification<Vendor> spec;
|
||||
RouteSpecification<Vendor> res = null;
|
||||
if (!all.isEmpty()){
|
||||
spec = RouteSpecificationByTargets.all(all);
|
||||
res = spec;
|
||||
for (Map.Entry<Long, List<Vendor>> entry : groupByTime(all).entrySet()) {
|
||||
spec = entry.getKey().equals(INFINITY_TIME) ?
|
||||
RouteSpecificationByTargets.all(entry.getValue()) :
|
||||
RouteSpecificationByTargets.all(entry.getValue(), entry.getKey());
|
||||
if (res != null){
|
||||
res = res.and(spec);
|
||||
} else {
|
||||
res = spec;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!any.isEmpty()){
|
||||
spec = any.size() > 1 ? RouteSpecificationByTargets.any(any) : new RouteSpecificationByTarget<>(any.iterator().next());
|
||||
if (res != null){
|
||||
res = res.and(spec);
|
||||
if (any.size() == 1){
|
||||
TimeEntry<Vendor> entry = any.iterator().next();
|
||||
spec = entry.time.equals(INFINITY_TIME) ?
|
||||
new RouteSpecificationByTarget<>(entry.obj) :
|
||||
new RouteSpecificationByTarget<>(entry.obj, entry.time);
|
||||
if (res != null){
|
||||
res = res.and(spec);
|
||||
} else {
|
||||
res = spec;
|
||||
}
|
||||
} else {
|
||||
res = spec;
|
||||
for (Map.Entry<Long, List<Vendor>> entry : groupByTime(any).entrySet()) {
|
||||
spec = entry.getKey().equals(INFINITY_TIME) ?
|
||||
RouteSpecificationByTargets.any(entry.getValue()) :
|
||||
RouteSpecificationByTargets.any(entry.getValue(), entry.getKey());
|
||||
if (res != null){
|
||||
res = res.and(spec);
|
||||
} else {
|
||||
res = spec;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!containsAny.isEmpty()){
|
||||
spec = RouteSpecificationByTargets.containAny(containsAny);
|
||||
if (res != null){
|
||||
res = res.and(spec);
|
||||
} else {
|
||||
res = spec;
|
||||
for (Map.Entry<Long, List<Vendor>> entry : groupByTime(containsAny).entrySet()) {
|
||||
spec = entry.getKey().equals(INFINITY_TIME) ?
|
||||
RouteSpecificationByTargets.containAny(entry.getValue()) :
|
||||
RouteSpecificationByTargets.containAny(entry.getValue(), entry.getKey());
|
||||
if (res != null){
|
||||
res = res.and(spec);
|
||||
} else {
|
||||
res = spec;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!offers.isEmpty()){
|
||||
@@ -173,4 +281,28 @@ public class CrawlerSpecificator {
|
||||
return build(vendors, onFoundFunc, null, false);
|
||||
}
|
||||
|
||||
private final static Long INFINITY_TIME = Long.MAX_VALUE;
|
||||
|
||||
private class TimeEntry<T> implements Comparable<TimeEntry<T>> {
|
||||
private final T obj;
|
||||
private final Long time;
|
||||
|
||||
private TimeEntry(T obj, Long time) {
|
||||
this.obj = obj;
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
private T getObj() {
|
||||
return obj;
|
||||
}
|
||||
|
||||
private Long getTime() {
|
||||
return time;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(TimeEntry<T> o) {
|
||||
return this.time.compareTo(o.time);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,8 +85,10 @@ public class RouteSearcher {
|
||||
RouteCollector collector = new RouteCollector();
|
||||
VendorsCrawlerSpecification specification = specificator.build(vendors, collector::add);
|
||||
Crawler<Vendor> crawler = vGraph.crawler(specification, callback);
|
||||
int lands = Math.max(scorer.getProfile().getLands(), specification.getMinLands());
|
||||
if (!specificator.isFullScan()) lands = specificator.getMinHop();
|
||||
int lands = specification.getMinLands();
|
||||
if (specificator.isFullScan()){
|
||||
lands = Math.max(scorer.getProfile().getLands(), lands);
|
||||
}
|
||||
crawler.setMaxSize(lands);
|
||||
crawler.findMin(target, count);
|
||||
return collector.get();
|
||||
@@ -103,13 +105,18 @@ public class RouteSearcher {
|
||||
specificator.setGroupCount(vendors.size());
|
||||
|
||||
VendorsCrawlerSpecification specification = specificator.build(vendors, collector::add, new LoopRouteSpecification<>(true), true);
|
||||
int lands = Math.max(scorer.getProfile().getLands(), specification.getMinLands());
|
||||
int lands = specification.getMinLands();
|
||||
if (specificator.isFullScan()){
|
||||
lands = Math.max(scorer.getProfile().getLands(), lands);
|
||||
}
|
||||
Crawler<Vendor> crawler = vGraph.crawler(specification, callback);
|
||||
crawler.setMaxSize(lands);
|
||||
crawler.findMin(source, vendors.size());
|
||||
specification = specificator.build(vendors, collector::add, new RouteSpecificationByTarget<>(source), false);
|
||||
lands = Math.max(scorer.getProfile().getLands(), specification.getMinLands());
|
||||
if (!specificator.isFullScan()) lands = specificator.getMinHop();
|
||||
lands = specification.getMinLands();
|
||||
if (specificator.isFullScan()){
|
||||
lands = Math.max(scorer.getProfile().getLands(), lands);
|
||||
}
|
||||
crawler = vGraph.crawler(specification, callback);
|
||||
crawler.setMaxSize(lands);
|
||||
crawler.findMin(source, 1);
|
||||
|
||||
@@ -14,7 +14,7 @@ public interface RouteSpecification<T> {
|
||||
public default boolean updateMutated(){return false;}
|
||||
public default boolean mutable(){return false;}
|
||||
public default void update(Traversal<T> entry){}
|
||||
public default void onAnd(RouteSpecification<T> other){}
|
||||
public default void onAnd(RouteSpecification<T> other){RouteSpecificationMixer.andMix(this, other);}
|
||||
public default void onOr(RouteSpecification<T> other){}
|
||||
|
||||
default RouteSpecification<T> and(final RouteSpecification<T> other){
|
||||
|
||||
@@ -6,25 +6,45 @@ import ru.trader.analysis.graph.Traversal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
public class RouteSpecificationByPair<T> implements RouteSpecification<T> {
|
||||
protected final Collection<T> first;
|
||||
protected final T second;
|
||||
protected final long time;
|
||||
private boolean checkSecond;
|
||||
|
||||
public RouteSpecificationByPair(T first, T second) {
|
||||
this(first, second, Long.MAX_VALUE);
|
||||
}
|
||||
|
||||
public RouteSpecificationByPair(T first, T second, long time) {
|
||||
this.first = new ArrayList<>();
|
||||
this.first.add(first);
|
||||
this.second = second;
|
||||
this.time = time;
|
||||
checkSecond = true;
|
||||
}
|
||||
|
||||
public RouteSpecificationByPair(Collection<T> first, T second) {
|
||||
this(first, second, Long.MAX_VALUE);
|
||||
}
|
||||
|
||||
public RouteSpecificationByPair(Collection<T> first, T second, long time) {
|
||||
this.first = new ArrayList<>(first);
|
||||
this.second = second;
|
||||
this.time = time;
|
||||
checkSecond = true;
|
||||
}
|
||||
|
||||
private boolean checkTime(){
|
||||
return time < Long.MAX_VALUE;
|
||||
}
|
||||
|
||||
protected void remove(){
|
||||
checkSecond = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean specified(Edge<T> edge, Traversal<T> entry) {
|
||||
return searchPair(edge, entry) == 0;
|
||||
@@ -32,6 +52,7 @@ public class RouteSpecificationByPair<T> implements RouteSpecification<T> {
|
||||
|
||||
@Override
|
||||
public boolean content(Edge<T> edge, Traversal<T> entry) {
|
||||
if (checkTime() && edge.getTime() + entry.getTime() > time) return false;
|
||||
T obj = edge.getTarget().getEntry();
|
||||
return second.equals(obj) || first.contains(obj);
|
||||
}
|
||||
@@ -47,51 +68,35 @@ public class RouteSpecificationByPair<T> implements RouteSpecification<T> {
|
||||
}
|
||||
|
||||
private int searchPair(Edge<T> edge, Traversal<T> entry){
|
||||
T obj = edge.getTarget().getEntry();
|
||||
int fIndex = -1;
|
||||
int sIndex = -1;
|
||||
if (first.contains(obj)){
|
||||
fIndex = 0;
|
||||
}
|
||||
if (second.equals(obj)){
|
||||
sIndex = 0;
|
||||
}
|
||||
if (sIndex != -1 && fIndex >= sIndex) return 0;
|
||||
|
||||
Iterator<Edge<T>> iterator = entry.routeIterator();
|
||||
int i = 1;
|
||||
while (iterator.hasNext()){
|
||||
obj = iterator.next().getTarget().getEntry();
|
||||
if (sIndex == -1 && second.equals(obj)){
|
||||
List<Traversal<T>> entries = entry.toList();
|
||||
int max = entries.size();
|
||||
for (int i = 0; i < max; i++) {
|
||||
Traversal<T> e = entries.get(i);
|
||||
T target = e.getTarget().getEntry();
|
||||
if (second.equals(target)){
|
||||
if (checkTime() && e.getTime() > time) return checkSecond ? 2 : 1;
|
||||
sIndex = i;
|
||||
}
|
||||
if (sIndex != -1 && fIndex >= sIndex){
|
||||
if (sIndex != -1 && fIndex != -1 && fIndex <= sIndex){
|
||||
return 0;
|
||||
}
|
||||
if (first.contains(obj)){
|
||||
if (fIndex == -1 && first.contains(target)){
|
||||
fIndex = i;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
T obj = edge.getTarget().getEntry();
|
||||
if (fIndex == -1 && first.contains(obj)){
|
||||
fIndex = max;
|
||||
}
|
||||
if (second.equals(obj)){
|
||||
if (checkTime() && edge.getTime() + entry.getTime() > time) return checkSecond ? 2 : 1;
|
||||
sIndex = max;
|
||||
}
|
||||
if (fIndex == -1) return checkSecond ? 2 : 1;
|
||||
if (sIndex == -1) return 1;
|
||||
return fIndex >= sIndex ? 0 : 1;
|
||||
if (sIndex == -1) return checkSecond ? 1 : 0;
|
||||
return fIndex <= sIndex ? 0 : 1;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onAnd(RouteSpecification<T> other) {
|
||||
if (other instanceof RouteSpecificationByTarget){
|
||||
if (checkSecond){
|
||||
T otherTarget = ((RouteSpecificationByTarget<T>)other).target;
|
||||
checkSecond = !second.equals(otherTarget);
|
||||
}
|
||||
} else
|
||||
if (other instanceof RouteSpecificationByPair){
|
||||
RouteSpecificationByPair<T> os = (RouteSpecificationByPair<T>)other;
|
||||
if (checkSecond && os.checkSecond){
|
||||
checkSecond = !second.equals(os.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,14 +4,34 @@ import ru.trader.analysis.graph.Edge;
|
||||
import ru.trader.analysis.graph.Traversal;
|
||||
|
||||
public class RouteSpecificationByTarget<T> implements RouteSpecification<T> {
|
||||
protected final T target;
|
||||
private T target;
|
||||
protected final long time;
|
||||
|
||||
public RouteSpecificationByTarget(T target) {
|
||||
this(target, Long.MAX_VALUE);
|
||||
}
|
||||
|
||||
public RouteSpecificationByTarget(T target, long time) {
|
||||
this.target = target;
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
private boolean checkTime(){
|
||||
return time < Long.MAX_VALUE;
|
||||
}
|
||||
|
||||
protected T getTarget(){
|
||||
return target;
|
||||
}
|
||||
|
||||
protected void remove(){
|
||||
target = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean specified(Edge<T> edge, Traversal<T> entry) {
|
||||
if (target == null) return true;
|
||||
if (checkTime() && edge.getTime() + entry.getTime() > time) return false;
|
||||
return edge.isConnect(target);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,35 +3,42 @@ package ru.trader.analysis;
|
||||
import ru.trader.analysis.graph.Edge;
|
||||
import ru.trader.analysis.graph.Traversal;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.*;
|
||||
|
||||
public class RouteSpecificationByTargets<T> implements RouteSpecification<T> {
|
||||
protected final Collection<T> targets;
|
||||
protected final boolean all;
|
||||
protected final boolean targetOnly;
|
||||
protected final long time;
|
||||
|
||||
private RouteSpecificationByTargets(Collection<T> targets, boolean all, boolean targetOnly) {
|
||||
protected RouteSpecificationByTargets(Collection<T> targets, long time, boolean all, boolean targetOnly) {
|
||||
this.all = all;
|
||||
this.targetOnly = targetOnly;
|
||||
this.targets = new HashSet<>(targets);
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
private boolean checkTime(){
|
||||
return time < Long.MAX_VALUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean specified(Edge<T> edge, Traversal<T> entry) {
|
||||
return targets.isEmpty() || (all ? containsAll(edge, entry) == 0 : containsAny(edge, entry) == 0);
|
||||
if (targets.isEmpty()) return true;
|
||||
if (checkTime() && targetOnly && edge.getTime() + entry.getTime() > time) return false;
|
||||
return all ? containsAll(edge, entry) == 0 : containsAny(edge, entry) == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean content(Edge<T> edge, Traversal<T> entry) {
|
||||
if (checkTime() && edge.getTime() + entry.getTime() > time) return false;
|
||||
return targets.contains(edge.getTarget().getEntry());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int lastFound(Edge<T> edge, Traversal<T> entry) {
|
||||
if (targets.isEmpty()) return 0;
|
||||
if (checkTime() && targetOnly && edge.getTime() + entry.getTime() > time) return matchCount();
|
||||
return all ? containsAll(edge, entry) : containsAny(edge, entry);
|
||||
}
|
||||
|
||||
@@ -41,63 +48,79 @@ public class RouteSpecificationByTargets<T> implements RouteSpecification<T> {
|
||||
return all ? targets.size() : 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnd(RouteSpecification<T> other) {
|
||||
if (other instanceof RouteSpecificationByTarget){
|
||||
T otherTarget = ((RouteSpecificationByTarget<T>)other).target;
|
||||
targets.remove(otherTarget);
|
||||
} else
|
||||
if (other instanceof RouteSpecificationByTargets){
|
||||
RouteSpecificationByTargets<T> os = ((RouteSpecificationByTargets<T>)other);
|
||||
if (os.all){
|
||||
Collection<T> otherTargets = ((RouteSpecificationByTargets<T>)other).targets;
|
||||
targets.removeAll(otherTargets);
|
||||
}
|
||||
} else
|
||||
if (other instanceof RouteSpecificationByPair){
|
||||
T otherTarget = ((RouteSpecificationByPair<T>)other).second;
|
||||
targets.remove(otherTarget);
|
||||
}
|
||||
}
|
||||
|
||||
private int containsAll(Edge<T> edge, Traversal<T> entry) {
|
||||
T obj = edge.getTarget().getEntry();
|
||||
Collection<T> set = new ArrayList<>(targets.size());
|
||||
set.add(obj);
|
||||
entry.routeIterator().forEachRemaining(e -> set.add(e.getTarget().getEntry()));
|
||||
int last = targets.size();
|
||||
for (T target : targets) {
|
||||
if (set.contains(target)){
|
||||
last--;
|
||||
Collection<T> founds = new HashSet<>();
|
||||
List<Traversal<T>> entries = entry.toList();
|
||||
for (Traversal<T> e : entries) {
|
||||
T target = e.getTarget().getEntry();
|
||||
if (targets.contains(target)){
|
||||
if (checkTime() && e.getTime() > time){
|
||||
return targets.size() - founds.size();
|
||||
} else {
|
||||
founds.add(target);
|
||||
}
|
||||
}
|
||||
if (targets.size() == founds.size()) return 0;
|
||||
}
|
||||
T target = edge.getTarget().getEntry();
|
||||
if (targets.contains(target)){
|
||||
if (checkTime() && edge.getTime() + entry.getTime() > time){
|
||||
return targets.size() - founds.size();
|
||||
} else {
|
||||
founds.add(target);
|
||||
}
|
||||
}
|
||||
return last;
|
||||
return targets.size() - founds.size();
|
||||
}
|
||||
|
||||
private int containsAny(Edge<T> edge, Traversal<T> entry) {
|
||||
T obj = edge.getTarget().getEntry();
|
||||
if (targets.contains(obj)) return 0;
|
||||
if (targets.contains(obj)){
|
||||
if (targetOnly){
|
||||
if (checkTime() && edge.getTime() + entry.getTime() > time) return 1;
|
||||
else return 0;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (targetOnly){
|
||||
return 1;
|
||||
}
|
||||
Iterator<Edge<T>> iterator = entry.routeIterator();
|
||||
while (iterator.hasNext()){
|
||||
if (targets.contains(iterator.next().getTarget().getEntry())){
|
||||
return 0;
|
||||
List<Traversal<T>> entries = entry.toList();
|
||||
for (Traversal<T> e : entries) {
|
||||
T target = e.getTarget().getEntry();
|
||||
if (targets.contains(target)){
|
||||
if (checkTime() && e.getTime() > time){
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
public static <T> RouteSpecificationByTargets<T> all(Collection<T> targets){
|
||||
return new RouteSpecificationByTargets<>(targets, true, false);
|
||||
return all(targets, Long.MAX_VALUE);
|
||||
}
|
||||
|
||||
public static <T> RouteSpecificationByTargets<T> all(Collection<T> targets, long time){
|
||||
return new RouteSpecificationByTargets<>(targets, time, true, false);
|
||||
}
|
||||
|
||||
public static <T> RouteSpecificationByTargets<T> any(Collection<T> targets){
|
||||
return new RouteSpecificationByTargets<>(targets, false, true);
|
||||
return any(targets, Long.MAX_VALUE);
|
||||
}
|
||||
|
||||
public static <T> RouteSpecificationByTargets<T> any(Collection<T> targets, long time){
|
||||
return new RouteSpecificationByTargets<>(targets, time, false, true);
|
||||
}
|
||||
|
||||
public static <T> RouteSpecificationByTargets<T> containAny(Collection<T> targets){
|
||||
return new RouteSpecificationByTargets<>(targets, false, false);
|
||||
return containAny(targets, Long.MAX_VALUE);
|
||||
}
|
||||
|
||||
public static <T> RouteSpecificationByTargets<T> containAny(Collection<T> targets, long time){
|
||||
return new RouteSpecificationByTargets<>(targets, time, false, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
package ru.trader.analysis;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public class RouteSpecificationMixer {
|
||||
public static <T> void andMix(RouteSpecificationByTargets<T> spec, RouteSpecification<T> other) {
|
||||
if (other instanceof RouteSpecificationByTarget){
|
||||
RouteSpecificationByTarget<T> os = (RouteSpecificationByTarget<T>)other;
|
||||
T otherTarget = os.getTarget();
|
||||
if (os.time < spec.time){
|
||||
spec.targets.remove(otherTarget);
|
||||
} else {
|
||||
if (spec.targetOnly && spec.targets.contains(otherTarget)){
|
||||
os.remove();
|
||||
}
|
||||
}
|
||||
} else
|
||||
if (other instanceof RouteSpecificationByTargets){
|
||||
RouteSpecificationByTargets<T> os = ((RouteSpecificationByTargets<T>)other);
|
||||
if (os.all){
|
||||
Collection<T> otherTargets = os.targets;
|
||||
if (os.time < spec.time){
|
||||
spec.targets.removeAll(otherTargets);
|
||||
} else {
|
||||
if (spec.all){
|
||||
os.targets.removeAll(spec.targets);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else
|
||||
if (other instanceof RouteSpecificationByPair){
|
||||
RouteSpecificationByPair<T> os = (RouteSpecificationByPair<T>)other;
|
||||
T otherTarget = os.second;
|
||||
if (os.time < spec.time){
|
||||
spec.targets.remove(otherTarget);
|
||||
} else {
|
||||
if (spec.targetOnly && spec.targets.contains(otherTarget)){
|
||||
os.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> void andMix(RouteSpecificationByTarget<T> spec, RouteSpecification<T> other) {
|
||||
if (other instanceof RouteSpecificationByTarget){
|
||||
RouteSpecificationByTarget<T> os = (RouteSpecificationByTarget<T>)other;
|
||||
T otherTarget = os.getTarget();
|
||||
if (spec.getTarget() == otherTarget){
|
||||
if (os.time < spec.time){
|
||||
spec.remove();
|
||||
} else {
|
||||
os.remove();
|
||||
}
|
||||
}
|
||||
} else
|
||||
if (other instanceof RouteSpecificationByTargets){
|
||||
RouteSpecificationByTargets<T> os = ((RouteSpecificationByTargets<T>)other);
|
||||
if (os.all){
|
||||
Collection<T> otherTargets = os.targets;
|
||||
if (otherTargets.contains(spec.getTarget())){
|
||||
if (os.time < spec.time){
|
||||
spec.remove();
|
||||
} else {
|
||||
os.targets.remove(spec.getTarget());
|
||||
}
|
||||
}
|
||||
}
|
||||
} else
|
||||
if (other instanceof RouteSpecificationByPair){
|
||||
RouteSpecificationByPair<T> os = (RouteSpecificationByPair<T>)other;
|
||||
T otherTarget = os.second;
|
||||
if (spec.getTarget() == otherTarget){
|
||||
if (os.time < spec.time){
|
||||
spec.remove();
|
||||
} else {
|
||||
os.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> void andMix(RouteSpecificationByPair<T> spec, RouteSpecification<T> other) {
|
||||
if (other instanceof RouteSpecificationByTarget){
|
||||
RouteSpecificationByTarget<T> os = (RouteSpecificationByTarget<T>)other;
|
||||
T otherTarget = os.getTarget();
|
||||
if (spec.second == otherTarget){
|
||||
if (os.time >= spec.time) {
|
||||
os.remove();
|
||||
}
|
||||
}
|
||||
} else
|
||||
if (other instanceof RouteSpecificationByTargets){
|
||||
RouteSpecificationByTargets<T> os = ((RouteSpecificationByTargets<T>)other);
|
||||
if (os.targetOnly){
|
||||
Collection<T> otherTargets = os.targets;
|
||||
if (otherTargets.contains(spec.second)){
|
||||
if (os.time >= spec.time) {
|
||||
os.targets.remove(spec.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else
|
||||
if (other instanceof RouteSpecificationByPair){
|
||||
RouteSpecificationByPair<T> os = (RouteSpecificationByPair<T>)other;
|
||||
boolean eqFirst = spec.first.containsAll(os.first);
|
||||
T otherTarget = os.second;
|
||||
if (eqFirst && spec.second == otherTarget){
|
||||
if (os.time < spec.time){
|
||||
spec.remove();
|
||||
} else {
|
||||
os.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> void andMix(RouteSpecification<T> spec, RouteSpecification<T> other) {
|
||||
if (spec instanceof RouteSpecificationByTarget){
|
||||
andMix((RouteSpecificationByTarget<T>)spec, other);
|
||||
} else
|
||||
if (spec instanceof RouteSpecificationByTargets){
|
||||
andMix((RouteSpecificationByTargets<T>)spec, other);
|
||||
} else
|
||||
if (spec instanceof RouteSpecificationByPair){
|
||||
andMix((RouteSpecificationByPair<T>)spec, other);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -51,6 +51,7 @@ public class VendorsCrawler extends Crawler<Vendor> {
|
||||
protected class VendorsTraversalEntry extends CostTraversalEntry {
|
||||
private final double fuel;
|
||||
private final double balance;
|
||||
private Long time;
|
||||
|
||||
protected VendorsTraversalEntry(CostTraversalEntry entry, double fuel, double balance) {
|
||||
super(entry.getTarget());
|
||||
@@ -101,6 +102,13 @@ public class VendorsCrawler extends Crawler<Vendor> {
|
||||
return weight;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getTime() {
|
||||
if (time == null){
|
||||
time = super.getTime();
|
||||
}
|
||||
return time;
|
||||
}
|
||||
|
||||
private Vendor findMarket(){
|
||||
Optional<Traversal<Vendor>> head = getHead();
|
||||
@@ -171,6 +179,7 @@ public class VendorsCrawler extends Crawler<Vendor> {
|
||||
return profitByTonne;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getTime() {
|
||||
if (time == null){
|
||||
time = computeTime();
|
||||
|
||||
@@ -33,6 +33,10 @@ public abstract class Edge<T> implements Comparable<Edge>{
|
||||
return target.getEntry().equals(other);
|
||||
}
|
||||
|
||||
public long getTime(){
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
|
||||
@@ -32,6 +32,15 @@ public interface Traversal<T> {
|
||||
return s;
|
||||
}
|
||||
|
||||
default long getTime(){
|
||||
Edge<T> edge = this.getEdge();
|
||||
long t = edge != null ? edge.getTime() : 0;
|
||||
if (this.getHead().isPresent()){
|
||||
t += getHead().get().getTime();
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
default List<Edge<T>> toEdges(){
|
||||
int s = size();
|
||||
@@ -48,6 +57,22 @@ public interface Traversal<T> {
|
||||
return Arrays.asList(res);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
default List<Traversal<T>> toList(){
|
||||
int s = size();
|
||||
Traversal<T>[] res = new Traversal[s];
|
||||
int i = s - 1;
|
||||
Traversal<T> entry = this;
|
||||
while (i >= 0){
|
||||
res[i]=entry;
|
||||
if (i > 0)
|
||||
entry = entry.getHead().get();
|
||||
i--;
|
||||
}
|
||||
return Arrays.asList(res);
|
||||
|
||||
}
|
||||
|
||||
default Iterator<Edge<T>> routeIterator(){
|
||||
return new Iterator<Edge<T>>() {
|
||||
private Edge<T> next = getEdge();
|
||||
|
||||
@@ -199,7 +199,7 @@ public class CrawlerSpecificatorTest extends Assert{
|
||||
VendorsCrawlerSpecification spec = specificator.build(vendors, edges -> {paths.add(RouteSearcher.toRoute(edges, vGraph.getScorer()));});
|
||||
|
||||
Crawler<Vendor> crawler = vGraph.crawler(spec, new AnalysisCallBack());
|
||||
crawler.setMaxSize(7);
|
||||
crawler.setMaxSize(spec.getMinLands());
|
||||
crawler.findMin(ithaca_st, 10);
|
||||
assertEquals(10, paths.size());
|
||||
for (Route path : paths) {
|
||||
|
||||
Reference in New Issue
Block a user