Archived
0

implement limit by time for crawler specification

This commit is contained in:
iMoHax
2015-11-20 16:10:59 +03:00
parent b805722edc
commit b0ef280c8f
11 changed files with 479 additions and 123 deletions

View File

@@ -6,26 +6,76 @@ import ru.trader.core.Vendor;
import java.util.*; import java.util.*;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public class CrawlerSpecificator { public class CrawlerSpecificator {
private final Set<Vendor> any; private final Collection<TimeEntry<Vendor>> any;
private final Set<Vendor> containsAny; private final Collection<TimeEntry<Vendor>> containsAny;
private final Set<Vendor> all; private final Collection<TimeEntry<Vendor>> all;
private final Collection<Offer> offers; private final Collection<TimeEntry<Offer>> offers;
private int groupCount; private int groupCount;
private boolean byTime; private boolean byTime;
private boolean fullScan; private boolean fullScan;
public CrawlerSpecificator() { public CrawlerSpecificator() {
any = new HashSet<>(); any = new ArrayList<>();
all = new HashSet<>(); all = new ArrayList<>();
containsAny = new HashSet<>(); containsAny = new ArrayList<>();
offers = new ArrayList<>(); offers = new ArrayList<>();
byTime = false; byTime = false;
fullScan = true; 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){ public void setByTime(boolean byTime){
this.byTime = byTime; this.byTime = byTime;
} }
@@ -39,43 +89,67 @@ public class CrawlerSpecificator {
} }
public void all(Collection<Vendor> vendors){ 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){ 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){ 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){ 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){ public void add(Vendor vendor, boolean required){
if (required){ if (required){
all.add(vendor); add(all, vendor);
} else { } 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){ if (required){
all.remove(vendor); add(all, time, vendor);
} else { } else {
any.remove(vendor); add(any, time, vendor);
} }
} }
public void buy(Offer offer){ 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){ 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) { public void setGroupCount(int groupCount) {
@@ -83,13 +157,14 @@ public class CrawlerSpecificator {
} }
public int getMinHop(){ 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){ 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; if (res) return true;
for (Offer offer : offers) { for (TimeEntry<Offer> entry : offers){
Offer offer = entry.obj;
Offer sell = vendor.getSell(offer.getItem()); Offer sell = vendor.getSell(offer.getItem());
res = sell != null && sell.getCount() >= offer.getCount(); res = sell != null && sell.getCount() >= offer.getCount();
if (res) return true; if (res) return true;
@@ -98,24 +173,29 @@ public class CrawlerSpecificator {
} }
public Collection<Vendor> getVendors(Collection<Vendor> vendors){ public Collection<Vendor> getVendors(Collection<Vendor> vendors){
Set<Vendor> v = new HashSet<>(containsAny); Set<Vendor> v = containsAny.stream().map(e -> e.obj).collect(Collectors.toSet());
v.addAll(any); any.stream().map(e -> e.obj).forEach(v::add);
v.addAll(all); all.stream().map(e -> e.obj).forEach(v::add);
offers.stream().map(e -> e.obj.getVendor()).forEach(v::add);
v.addAll(vendors); v.addAll(vendors);
return v; return v;
} }
private RouteSpecification<Vendor> buildOffersSpec(Collection<Vendor> vendors){ private RouteSpecification<Vendor> buildOffersSpec(Collection<Vendor> vendors){
RouteSpecification<Vendor> res = null; RouteSpecification<Vendor> res = null;
for (Offer offer : offers) { for (TimeEntry<Offer> entry : offers) {
Offer offer = entry.obj;
List<Vendor> sellers = vendors.stream().filter(v -> { List<Vendor> sellers = vendors.stream().filter(v -> {
Offer sell = v.getSell(offer.getItem()); Offer sell = v.getSell(offer.getItem());
return sell != null && sell.getCount() >= offer.getCount(); return sell != null && sell.getCount() >= offer.getCount();
}).collect(Collectors.toList()); }).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){ if (res != null){
res = res.and(new RouteSpecificationByPair<>(sellers, offer.getVendor())); res = res.and(spec);
} else { } else {
res = new RouteSpecificationByPair<>(sellers, offer.getVendor()); res = spec;
} }
} }
return res; return res;
@@ -125,25 +205,53 @@ public class CrawlerSpecificator {
RouteSpecification<Vendor> spec; RouteSpecification<Vendor> spec;
RouteSpecification<Vendor> res = null; RouteSpecification<Vendor> res = null;
if (!all.isEmpty()){ if (!all.isEmpty()){
spec = RouteSpecificationByTargets.all(all); for (Map.Entry<Long, List<Vendor>> entry : groupByTime(all).entrySet()) {
res = spec; spec = entry.getKey().equals(INFINITY_TIME) ?
} RouteSpecificationByTargets.all(entry.getValue()) :
if (!any.isEmpty()){ RouteSpecificationByTargets.all(entry.getValue(), entry.getKey());
spec = any.size() > 1 ? RouteSpecificationByTargets.any(any) : new RouteSpecificationByTarget<>(any.iterator().next());
if (res != null){ if (res != null){
res = res.and(spec); res = res.and(spec);
} else { } else {
res = spec; res = spec;
} }
} }
}
if (!any.isEmpty()){
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 {
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()){ if (!containsAny.isEmpty()){
spec = RouteSpecificationByTargets.containAny(containsAny); 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){ if (res != null){
res = res.and(spec); res = res.and(spec);
} else { } else {
res = spec; res = spec;
} }
} }
}
if (!offers.isEmpty()){ if (!offers.isEmpty()){
spec = buildOffersSpec(vendors); spec = buildOffersSpec(vendors);
if (res != null){ if (res != null){
@@ -173,4 +281,28 @@ public class CrawlerSpecificator {
return build(vendors, onFoundFunc, null, false); 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);
}
}
} }

View File

@@ -85,8 +85,10 @@ public class RouteSearcher {
RouteCollector collector = new RouteCollector(); RouteCollector collector = new RouteCollector();
VendorsCrawlerSpecification specification = specificator.build(vendors, collector::add); VendorsCrawlerSpecification specification = specificator.build(vendors, collector::add);
Crawler<Vendor> crawler = vGraph.crawler(specification, callback); Crawler<Vendor> crawler = vGraph.crawler(specification, callback);
int lands = Math.max(scorer.getProfile().getLands(), specification.getMinLands()); int lands = specification.getMinLands();
if (!specificator.isFullScan()) lands = specificator.getMinHop(); if (specificator.isFullScan()){
lands = Math.max(scorer.getProfile().getLands(), lands);
}
crawler.setMaxSize(lands); crawler.setMaxSize(lands);
crawler.findMin(target, count); crawler.findMin(target, count);
return collector.get(); return collector.get();
@@ -103,13 +105,18 @@ public class RouteSearcher {
specificator.setGroupCount(vendors.size()); specificator.setGroupCount(vendors.size());
VendorsCrawlerSpecification specification = specificator.build(vendors, collector::add, new LoopRouteSpecification<>(true), true); 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<Vendor> crawler = vGraph.crawler(specification, callback);
crawler.setMaxSize(lands); crawler.setMaxSize(lands);
crawler.findMin(source, vendors.size()); crawler.findMin(source, vendors.size());
specification = specificator.build(vendors, collector::add, new RouteSpecificationByTarget<>(source), false); specification = specificator.build(vendors, collector::add, new RouteSpecificationByTarget<>(source), false);
lands = Math.max(scorer.getProfile().getLands(), specification.getMinLands()); lands = specification.getMinLands();
if (!specificator.isFullScan()) lands = specificator.getMinHop(); if (specificator.isFullScan()){
lands = Math.max(scorer.getProfile().getLands(), lands);
}
crawler = vGraph.crawler(specification, callback); crawler = vGraph.crawler(specification, callback);
crawler.setMaxSize(lands); crawler.setMaxSize(lands);
crawler.findMin(source, 1); crawler.findMin(source, 1);

View File

@@ -14,7 +14,7 @@ public interface RouteSpecification<T> {
public default boolean updateMutated(){return false;} public default boolean updateMutated(){return false;}
public default boolean mutable(){return false;} public default boolean mutable(){return false;}
public default void update(Traversal<T> entry){} 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){} public default void onOr(RouteSpecification<T> other){}
default RouteSpecification<T> and(final RouteSpecification<T> other){ default RouteSpecification<T> and(final RouteSpecification<T> other){

View File

@@ -6,25 +6,45 @@ import ru.trader.analysis.graph.Traversal;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Iterator; import java.util.Iterator;
import java.util.List;
public class RouteSpecificationByPair<T> implements RouteSpecification<T> { public class RouteSpecificationByPair<T> implements RouteSpecification<T> {
protected final Collection<T> first; protected final Collection<T> first;
protected final T second; protected final T second;
protected final long time;
private boolean checkSecond; private boolean checkSecond;
public RouteSpecificationByPair(T first, T second) { 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 = new ArrayList<>();
this.first.add(first); this.first.add(first);
this.second = second; this.second = second;
this.time = time;
checkSecond = true; checkSecond = true;
} }
public RouteSpecificationByPair(Collection<T> first, T second) { 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.first = new ArrayList<>(first);
this.second = second; this.second = second;
this.time = time;
checkSecond = true; checkSecond = true;
} }
private boolean checkTime(){
return time < Long.MAX_VALUE;
}
protected void remove(){
checkSecond = false;
}
@Override @Override
public boolean specified(Edge<T> edge, Traversal<T> entry) { public boolean specified(Edge<T> edge, Traversal<T> entry) {
return searchPair(edge, entry) == 0; return searchPair(edge, entry) == 0;
@@ -32,6 +52,7 @@ public class RouteSpecificationByPair<T> implements RouteSpecification<T> {
@Override @Override
public boolean content(Edge<T> edge, Traversal<T> entry) { public boolean content(Edge<T> edge, Traversal<T> entry) {
if (checkTime() && edge.getTime() + entry.getTime() > time) return false;
T obj = edge.getTarget().getEntry(); T obj = edge.getTarget().getEntry();
return second.equals(obj) || first.contains(obj); 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){ private int searchPair(Edge<T> edge, Traversal<T> entry){
T obj = edge.getTarget().getEntry();
int fIndex = -1; int fIndex = -1;
int sIndex = -1; int sIndex = -1;
if (first.contains(obj)){ List<Traversal<T>> entries = entry.toList();
fIndex = 0; int max = entries.size();
} for (int i = 0; i < max; i++) {
if (second.equals(obj)){ Traversal<T> e = entries.get(i);
sIndex = 0; T target = e.getTarget().getEntry();
} if (second.equals(target)){
if (sIndex != -1 && fIndex >= sIndex) return 0; if (checkTime() && e.getTime() > time) return checkSecond ? 2 : 1;
Iterator<Edge<T>> iterator = entry.routeIterator();
int i = 1;
while (iterator.hasNext()){
obj = iterator.next().getTarget().getEntry();
if (sIndex == -1 && second.equals(obj)){
sIndex = i; sIndex = i;
} }
if (sIndex != -1 && fIndex >= sIndex){ if (sIndex != -1 && fIndex != -1 && fIndex <= sIndex){
return 0; return 0;
} }
if (first.contains(obj)){ if (fIndex == -1 && first.contains(target)){
fIndex = i; 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 (fIndex == -1) return checkSecond ? 2 : 1;
if (sIndex == -1) return 1; if (sIndex == -1) return checkSecond ? 1 : 0;
return fIndex >= sIndex ? 0 : 1; 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);
}
}
}
} }

View File

@@ -4,14 +4,34 @@ import ru.trader.analysis.graph.Edge;
import ru.trader.analysis.graph.Traversal; import ru.trader.analysis.graph.Traversal;
public class RouteSpecificationByTarget<T> implements RouteSpecification<T> { public class RouteSpecificationByTarget<T> implements RouteSpecification<T> {
protected final T target; private T target;
protected final long time;
public RouteSpecificationByTarget(T target) { public RouteSpecificationByTarget(T target) {
this(target, Long.MAX_VALUE);
}
public RouteSpecificationByTarget(T target, long time) {
this.target = target; 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 @Override
public boolean specified(Edge<T> edge, Traversal<T> entry) { 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); return edge.isConnect(target);
} }
} }

View File

@@ -3,35 +3,42 @@ package ru.trader.analysis;
import ru.trader.analysis.graph.Edge; import ru.trader.analysis.graph.Edge;
import ru.trader.analysis.graph.Traversal; import ru.trader.analysis.graph.Traversal;
import java.util.ArrayList; import java.util.*;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
public class RouteSpecificationByTargets<T> implements RouteSpecification<T> { public class RouteSpecificationByTargets<T> implements RouteSpecification<T> {
protected final Collection<T> targets; protected final Collection<T> targets;
protected final boolean all; protected final boolean all;
protected final boolean targetOnly; 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.all = all;
this.targetOnly = targetOnly; this.targetOnly = targetOnly;
this.targets = new HashSet<>(targets); this.targets = new HashSet<>(targets);
this.time = time;
}
private boolean checkTime(){
return time < Long.MAX_VALUE;
} }
@Override @Override
public boolean specified(Edge<T> edge, Traversal<T> entry) { 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 @Override
public boolean content(Edge<T> edge, Traversal<T> entry) { public boolean content(Edge<T> edge, Traversal<T> entry) {
if (checkTime() && edge.getTime() + entry.getTime() > time) return false;
return targets.contains(edge.getTarget().getEntry()); return targets.contains(edge.getTarget().getEntry());
} }
@Override @Override
public int lastFound(Edge<T> edge, Traversal<T> entry) { public int lastFound(Edge<T> edge, Traversal<T> entry) {
if (targets.isEmpty()) return 0; if (targets.isEmpty()) return 0;
if (checkTime() && targetOnly && edge.getTime() + entry.getTime() > time) return matchCount();
return all ? containsAll(edge, entry) : containsAny(edge, entry); return all ? containsAll(edge, entry) : containsAny(edge, entry);
} }
@@ -41,63 +48,79 @@ public class RouteSpecificationByTargets<T> implements RouteSpecification<T> {
return all ? targets.size() : 1; 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) { private int containsAll(Edge<T> edge, Traversal<T> entry) {
T obj = edge.getTarget().getEntry(); Collection<T> founds = new HashSet<>();
Collection<T> set = new ArrayList<>(targets.size()); List<Traversal<T>> entries = entry.toList();
set.add(obj); for (Traversal<T> e : entries) {
entry.routeIterator().forEachRemaining(e -> set.add(e.getTarget().getEntry())); T target = e.getTarget().getEntry();
int last = targets.size(); if (targets.contains(target)){
for (T target : targets) { if (checkTime() && e.getTime() > time){
if (set.contains(target)){ return targets.size() - founds.size();
last--; } else {
founds.add(target);
} }
} }
return last; 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 targets.size() - founds.size();
} }
private int containsAny(Edge<T> edge, Traversal<T> entry) { private int containsAny(Edge<T> edge, Traversal<T> entry) {
T obj = edge.getTarget().getEntry(); 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){ if (targetOnly){
return 1; return 1;
} }
Iterator<Edge<T>> iterator = entry.routeIterator(); List<Traversal<T>> entries = entry.toList();
while (iterator.hasNext()){ for (Traversal<T> e : entries) {
if (targets.contains(iterator.next().getTarget().getEntry())){ T target = e.getTarget().getEntry();
if (targets.contains(target)){
if (checkTime() && e.getTime() > time){
return 1;
} else {
return 0; return 0;
} }
} }
}
return 1; return 1;
} }
public static <T> RouteSpecificationByTargets<T> all(Collection<T> targets){ 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){ 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){ 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);
} }
} }

View File

@@ -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);
}
}
}

View File

@@ -51,6 +51,7 @@ public class VendorsCrawler extends Crawler<Vendor> {
protected class VendorsTraversalEntry extends CostTraversalEntry { protected class VendorsTraversalEntry extends CostTraversalEntry {
private final double fuel; private final double fuel;
private final double balance; private final double balance;
private Long time;
protected VendorsTraversalEntry(CostTraversalEntry entry, double fuel, double balance) { protected VendorsTraversalEntry(CostTraversalEntry entry, double fuel, double balance) {
super(entry.getTarget()); super(entry.getTarget());
@@ -101,6 +102,13 @@ public class VendorsCrawler extends Crawler<Vendor> {
return weight; return weight;
} }
@Override
public long getTime() {
if (time == null){
time = super.getTime();
}
return time;
}
private Vendor findMarket(){ private Vendor findMarket(){
Optional<Traversal<Vendor>> head = getHead(); Optional<Traversal<Vendor>> head = getHead();
@@ -171,6 +179,7 @@ public class VendorsCrawler extends Crawler<Vendor> {
return profitByTonne; return profitByTonne;
} }
@Override
public long getTime() { public long getTime() {
if (time == null){ if (time == null){
time = computeTime(); time = computeTime();

View File

@@ -33,6 +33,10 @@ public abstract class Edge<T> implements Comparable<Edge>{
return target.getEntry().equals(other); return target.getEntry().equals(other);
} }
public long getTime(){
return 1;
}
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (this == o) return true; if (this == o) return true;

View File

@@ -32,6 +32,15 @@ public interface Traversal<T> {
return s; 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") @SuppressWarnings("unchecked")
default List<Edge<T>> toEdges(){ default List<Edge<T>> toEdges(){
int s = size(); int s = size();
@@ -48,6 +57,22 @@ public interface Traversal<T> {
return Arrays.asList(res); 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(){ default Iterator<Edge<T>> routeIterator(){
return new Iterator<Edge<T>>() { return new Iterator<Edge<T>>() {
private Edge<T> next = getEdge(); private Edge<T> next = getEdge();

View File

@@ -199,7 +199,7 @@ public class CrawlerSpecificatorTest extends Assert{
VendorsCrawlerSpecification spec = specificator.build(vendors, edges -> {paths.add(RouteSearcher.toRoute(edges, vGraph.getScorer()));}); VendorsCrawlerSpecification spec = specificator.build(vendors, edges -> {paths.add(RouteSearcher.toRoute(edges, vGraph.getScorer()));});
Crawler<Vendor> crawler = vGraph.crawler(spec, new AnalysisCallBack()); Crawler<Vendor> crawler = vGraph.crawler(spec, new AnalysisCallBack());
crawler.setMaxSize(7); crawler.setMaxSize(spec.getMinLands());
crawler.findMin(ithaca_st, 10); crawler.findMin(ithaca_st, 10);
assertEquals(10, paths.size()); assertEquals(10, paths.size());
for (Route path : paths) { for (Route path : paths) {