Archived
0

progress dialog prototype

This commit is contained in:
iMoHax
2015-01-11 13:55:48 +03:00
parent 1a327f14a6
commit 62d951a674
11 changed files with 560 additions and 55 deletions

View File

@@ -10,6 +10,7 @@ public class MarketAnalyzer {
private final static Logger LOG = LoggerFactory.getLogger(MarketAnalyzer.class);
private final Market market;
private MarketAnalyzerCallBack callback;
private MarketFilter filter;
private double tank;
private double maxDistance;
@@ -21,11 +22,20 @@ public class MarketAnalyzer {
private final static Comparator<Order> orderComparator = (o1, o2) -> o2.compareTo(o1);
public MarketAnalyzer(Market market) {
this(market, new MarketAnalyzerCallBack());
}
public MarketAnalyzer(Market market, MarketAnalyzerCallBack callback) {
this.market = market;
this.callback = callback;
this.limit = 100;
this.segmentSize = 0;
}
public void setCallback(MarketAnalyzerCallBack callback) {
this.callback = callback;
}
public void setFilter(MarketFilter filter) {
this.filter = filter;
}
@@ -56,19 +66,23 @@ public class MarketAnalyzer {
public Collection<Order> getTop(double balance){
LOG.debug("Get top {}", limit);
Iterable<Place> places = getPlaces();
Collection<Place> places = getPlaces();
List<Order> top = new ArrayList<>(limit);
callback.setCount(places.size());
for (Place place : places) {
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);
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);
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);
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);
}
@@ -78,18 +92,22 @@ public class MarketAnalyzer {
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);
Graph<Place> graph = new Graph<>(place, places, tank, maxDistance, true, jumps, Path::new, callback.onStartGraph());
return getOrders(graph, place.get(), balance, lowProfit);
}
private Collection<Order> getOrders(Graph<Place> graph, Collection<Vendor> sellers, double balance, double lowProfit) {
List<Order> res = new ArrayList<>(20);
callback.setCount(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);
@@ -97,6 +115,7 @@ public class MarketAnalyzer {
if (count == 0) continue;
Iterator<Offer> buyers = market.getStatBuy(sell.getItem()).getOffers().descendingIterator();
while (buyers.hasNext()){
if (callback.isCancel()) break;
Offer buy = buyers.next();
if (isFiltered(buy.getVendor())){
LOG.trace("Is filtered, skip");
@@ -116,6 +135,7 @@ public class MarketAnalyzer {
res.add(order);
}
}
callback.inc();
}
res.sort(orderComparator);
return res;
@@ -123,17 +143,22 @@ public class MarketAnalyzer {
private Collection<Order> getOrders(Collection<Vendor> sellers, Collection<Vendor> buyers, double balance, double lowProfit) {
List<Order> res = new ArrayList<>();
callback.setCount(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);
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;
@@ -150,6 +175,7 @@ public class MarketAnalyzer {
}
}
}
callback.inc();
}
res.sort(orderComparator);
return res;
@@ -209,98 +235,131 @@ public class MarketAnalyzer {
}
public Collection<PathRoute> getPaths(Vendor from, double balance){
RouteSearcher searcher = new RouteSearcher(maxDistance, tank, segmentSize);
callback.setCount(1);
RouteSearcher searcher = new RouteSearcher(maxDistance, tank, segmentSize, callback.onStartSearch());
Collection<Vendor> vendors = getVendors();
return searcher.getPaths(from, vendors, jumps, balance, cargo, limit);
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){
RouteSearcher searcher = new RouteSearcher(maxDistance, tank, segmentSize);
List<PathRoute> top = new ArrayList<>(limit);
Collection<Vendor> vendors = getVendors();
callback.setCount(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);
if (paths.size()>0){
return paths;
}
TopList.addAllToTop(top, paths, limit, RouteGraph.byProfitComparator);
callback.inc();
}
return Collections.emptyList();
callback.onEndSearch();
return top;
}
public Collection<PathRoute> getPaths(Vendor from, Vendor to, double balance){
RouteSearcher searcher = new RouteSearcher(maxDistance, tank, segmentSize);
return searcher.getPaths(from, to, getVendors(), jumps, balance, cargo, limit);
callback.setCount(1);
RouteSearcher searcher = new RouteSearcher(maxDistance, tank, segmentSize, callback.onStartSearch());
Collection<PathRoute> res = searcher.getPaths(from, to, getVendors(), 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);
RouteSearcher searcher = new RouteSearcher(maxDistance, tank, segmentSize);
Collection<Vendor> vendors = getVendors();
Collection<Vendor> fVendors = from.get();
Collection<Vendor> toVendors = to.get();
int count = (int) Math.ceil(limit / fVendors.size());
callback.setCount(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);
RouteSearcher searcher = new RouteSearcher(maxDistance, tank, segmentSize);
Collection<Vendor> vendors = getVendors();
Collection<Vendor> toVendors = to.get();
int count = (int) Math.ceil(limit / toVendors.size());
callback.setCount(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);
RouteSearcher searcher = new RouteSearcher(maxDistance, tank, segmentSize);
Collection<Vendor> vendors = getVendors();
Collection<Vendor> fVendors = from.get();
int count = (int) Math.ceil(limit / fVendors.size());
callback.setCount(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);
RouteSearcher searcher = new RouteSearcher(maxDistance, tank, segmentSize);
Collection<Vendor> vendors = getVendors();
callback.setCount(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);
callback.inc();
}
callback.onEndSearch();
return top;
}

View File

@@ -0,0 +1,62 @@
package ru.trader.core;
import ru.trader.graph.GraphCallBack;
import ru.trader.graph.RouteSearcherCallBack;
public class MarketAnalyzerCallBack {
private volatile boolean cancel = false;
private RouteSearcherCallBack callbackRoute;
private GraphCallBack<Place> callbackGraph;
protected RouteSearcherCallBack getRouteSearcherCallBackInstance(){
return new RouteSearcherCallBack();
}
protected GraphCallBack<Place> getGraphCallBackInstance(){
return new GraphCallBack<>();
}
public final GraphCallBack<Place> onStartGraph(){
callbackGraph = getGraphCallBackInstance();
return callbackGraph;
}
public final void onEndGraph(){
callbackGraph = null;
}
public final RouteSearcherCallBack onStartSearch(){
callbackRoute = getRouteSearcherCallBackInstance();
return callbackRoute;
}
public final void onEndSearch(){
callbackRoute = null;
onEnd();
}
protected void onEnd(){}
public void setCount(long count){}
public void inc(){}
public final boolean isCancel() {
return cancel;
}
public final void cancel(){
if (cancel) return;
this.cancel = true;
if (callbackRoute != null){
callbackRoute.cancel();
callbackRoute = null;
}
if (callbackGraph != null){
callbackGraph.cancel();
callbackGraph = null;
}
}
}

View File

@@ -23,6 +23,7 @@ public class Graph<T extends Connectable<T>> {
protected final Vertex<T> root;
protected final Map<T,Vertex<T>> vertexes;
private final GraphCallBack<T> callback;
protected final double stock;
protected final double maxDistance;
@@ -48,15 +49,22 @@ public class Graph<T extends Connectable<T>> {
}
public Graph(T start, Collection<T> set, double stock, double maxDistance, boolean withRefill, int maxDeep, PathConstructor<T> pathFabric) {
this(start, set, stock, maxDistance, withRefill, maxDeep, pathFabric, new GraphCallBack<>());
}
public Graph(T start, Collection<T> set, double stock, double maxDistance, boolean withRefill, int maxDeep, PathConstructor<T> pathFabric, GraphCallBack<T> callback) {
this.maxDistance = maxDistance;
this.stock = stock;
this.withRefill = withRefill;
this.pathFabric = pathFabric;
this.callback = callback;
root = new Vertex<>(start);
root.setLevel(maxDeep);
vertexes = new ConcurrentHashMap<>(50, 0.9f, THRESHOLD);
vertexes.put(root.getEntry(), root);
callback.onStartBuild(start);
build(root, set, maxDeep, stock);
callback.onEndBuild();
}
private void build(Vertex<T> root, Collection<T> set, int maxDeep, double stock) {
@@ -81,7 +89,9 @@ public class Graph<T extends Connectable<T>> {
}
private void findPathsTo(Vertex<T> target, TopList<Path<T>> res, int deep){
callback.onStartFind(root, target);
POOL.invoke(new PathFinder(res, pathFabric.build(root), target, deep-1, stock));
callback.onEndFind();
}
public List<Path<T>> getPathsTo(T entry){
@@ -95,7 +105,9 @@ public class Graph<T extends Connectable<T>> {
public TopList<Path<T>> getPathsTo(T entry, int max, int deep){
Vertex<T> target = getVertex(entry);
TopList<Path<T>> paths = newTopList(max);
callback.setCount(1);
findPathsTo(target, paths, deep);
callback.inc();
paths.finish();
return paths;
}
@@ -106,12 +118,15 @@ public class Graph<T extends Connectable<T>> {
public TopList<Path<T>> getPaths(int count, int deep){
TopList<Path<T>> paths = newTopList(count);
callback.setCount(vertexes.size());
for (Vertex<T> target : vertexes.values()) {
if (callback.isCancel()) break;
TopList<Path<T>> p = newTopList(minJumps);
findPathsTo(target, p, deep);
for (Path<T> path : p.getList()) {
paths.add(path);
}
callback.inc();
}
paths.finish();
return paths;
@@ -204,6 +219,7 @@ public class Graph<T extends Connectable<T>> {
ArrayList<GraphBuilder> subTasks = new ArrayList<>(set.size());
Iterator<T> iterator = set.iterator();
while (iterator.hasNext()) {
if (callback.isCancel()) break;
T entry = iterator.next();
if (entry == vertex.getEntry()) continue;
double distance = vertex.getEntry().getDistance(entry);
@@ -236,14 +252,22 @@ public class Graph<T extends Connectable<T>> {
}
if (subTasks.size() == THRESHOLD || !iterator.hasNext()){
for (GraphBuilder subTask : subTasks) {
subTask.join();
if (callback.isCancel()){
subTask.cancel(true);
} else {
subTask.join();
}
}
subTasks.clear();
}
}
if (!subTasks.isEmpty()){
for (GraphBuilder subTask : subTasks) {
subTask.join();
if (callback.isCancel()){
subTask.cancel(true);
} else {
subTask.join();
}
}
subTasks.clear();
}
@@ -282,6 +306,7 @@ public class Graph<T extends Connectable<T>> {
synchronized (paths){
if (!paths.add(path)) complete(null);
}
callback.onFound();
}
}
if (deep > 0 ){
@@ -291,7 +316,7 @@ public class Graph<T extends Connectable<T>> {
Iterator<Edge<T>> iterator = source.getEdges().iterator();
while (iterator.hasNext()) {
Edge<T> next = iterator.next();
if (isDone()) break;
if (isDone() || callback.isCancel()) break;
// target already added if source consist edge
if (next.isConnect(target)) continue;
if (!distanceFilter.test(next.getLength())) continue;
@@ -305,8 +330,8 @@ public class Graph<T extends Connectable<T>> {
subTasks.add(task);
if (subTasks.size() == THRESHOLD || !iterator.hasNext()){
for (PathFinder subTask : subTasks) {
if (isDone()) {
subTask.cancel(false);
if (isDone() || callback.isCancel()) {
subTask.cancel(callback.isCancel());
} else {
subTask.join();
}
@@ -316,8 +341,8 @@ public class Graph<T extends Connectable<T>> {
}
if (!subTasks.isEmpty()){
for (PathFinder subTask : subTasks) {
if (isDone()) {
subTask.cancel(false);
if (isDone() || callback.isCancel()) {
subTask.cancel(callback.isCancel());
} else {
subTask.join();
}

View File

@@ -0,0 +1,27 @@
package ru.trader.graph;
public class GraphCallBack<T extends Connectable<T>> {
private volatile boolean cancel = false;
public void onStartBuild(T from){}
public void onEndBuild(){}
public void onStartFind(Vertex<T> from, Vertex<T> to){}
public void onFound(){}
public void onEndFind(){}
public void setCount(long count){}
public void inc(){}
public final boolean isCancel() {
return cancel;
}
public final void cancel(){
this.cancel = true;
}
}

View File

@@ -31,9 +31,12 @@ public class RouteGraph extends Graph<Vendor> {
public RouteGraph(Vendor start, Collection<Vendor> set, double stock, double maxDistance, boolean withRefill, int maxDeep) {
this(start, set, stock, maxDistance, withRefill, maxDeep, false);
}
public RouteGraph(Vendor start, Collection<Vendor> set, double stock, double maxDistance, boolean withRefill, int maxDeep, boolean groupRes) {
super(start, set, stock, maxDistance, withRefill, maxDeep, groupRes ? PathRoute::buildAvg : PathRoute::new);
this(start, set, stock, maxDistance, withRefill, maxDeep, groupRes, new GraphCallBack<>());
}
public RouteGraph(Vendor start, Collection<Vendor> set, double stock, double maxDistance, boolean withRefill, int maxDeep, boolean groupRes, GraphCallBack<Vendor> callback) {
super(start, set, stock, maxDistance, withRefill, maxDeep, groupRes ? PathRoute::buildAvg : PathRoute::new, callback);
if (groupRes){
this.groupRes = maxDeep > minJumps;
}

View File

@@ -14,17 +14,19 @@ public class RouteSearcher {
private final static ForkJoinPool POOL = new ForkJoinPool();
private final static int THRESHOLD = (int) Math.ceil(Runtime.getRuntime().availableProcessors()/2.0);
private final RouteSearcherCallBack callback;
private final double maxDistance;
private final double stock;
private final int segmentSize;
public RouteSearcher(double maxDistance, double stock) {
this(maxDistance, stock, 0);
this(maxDistance, stock, 0, new RouteSearcherCallBack());
}
public RouteSearcher(double maxDistance, double stock, int segmentSize) {
public RouteSearcher(double maxDistance, double stock, int segmentSize, RouteSearcherCallBack callback) {
this.maxDistance = maxDistance;
this.stock = stock;
this.segmentSize = segmentSize;
this.callback = callback;
}
public List<PathRoute> getPaths(Vendor from, Vendor to, Collection<Vendor> vendors, int jumps, double balance, int cargo, int limit){
@@ -56,8 +58,10 @@ public class RouteSearcher {
@Override
protected List<PathRoute> compute() {
if (callback.isCancel()) return Collections.emptyList();
LOG.trace("Start search route to {} from {}, jumps {}", source, target, jumps);
RouteGraph sGraph = new RouteGraph(source, vendors, stock, maxDistance, true, jumps, true);
GraphCallBack<Vendor> gCallBack = callback.onStart();
RouteGraph sGraph = new RouteGraph(source, vendors, stock, maxDistance, true, jumps, true, gCallBack);
int jumpsToAll = sGraph.getMinJumps();
LOG.trace("Segment jumps {}", jumpsToAll);
sGraph.setCargo(cargo);
@@ -87,8 +91,10 @@ public class RouteSearcher {
res.add(path);
}
}
if (callback.isCancel()) break;
subTasks.clear();
for (int taskIndex = 0; taskIndex < THRESHOLD && i+taskIndex < paths.size(); taskIndex++) {
if (callback.isCancel()) break;
PathRoute path = (PathRoute) paths.get(i+taskIndex);
double newBalance = balance + path.getRoot().getProfit();
SegmentSearcher task = new SegmentSearcher(path.get(), target, vendors, jumps - path.getLength(), newBalance, cargo, 1);
@@ -103,6 +109,7 @@ public class RouteSearcher {
}
}
res.finish();
callback.onEnd(gCallBack);
return res.getList();
}
@@ -116,6 +123,10 @@ public class RouteSearcher {
private void add(SegmentSearcher task, PathRoute path, TopList<PathRoute> res){
if (callback.isCancel()){
task.cancel(true);
return;
}
List<PathRoute> tail = task.join();
if (tail.isEmpty()){
LOG.trace("Not found route from {} to {}, jumps {}", task.source, task.target, task.jumps);

View File

@@ -0,0 +1,44 @@
package ru.trader.graph;
import ru.trader.core.Vendor;
import java.util.LinkedList;
import java.util.List;
public class RouteSearcherCallBack {
private volatile boolean cancel = false;
private final List<GraphCallBack<Vendor>> callbacks = new LinkedList<>();
public final GraphCallBack<Vendor> onStart(){
GraphCallBack<Vendor> callback = getGraphCallBackInstance();
if (cancel) return callback;
synchronized (callbacks) {
callbacks.add(callback);
}
return callback;
}
public final void onEnd( GraphCallBack<Vendor> callback){
synchronized (callbacks) {
callbacks.remove(callback);
}
}
protected GraphCallBack<Vendor> getGraphCallBackInstance(){
return new GraphCallBack<>();
}
public final boolean isCancel() {
return cancel;
}
public final void cancel(){
if (cancel) return;
this.cancel = true;
synchronized (callbacks){
callbacks.forEach(GraphCallBack::cancel);
callbacks.clear();
}
}
}