Implement path find
This commit is contained in:
@@ -3,12 +3,10 @@ package ru.trader.controllers;
|
|||||||
|
|
||||||
import javafx.collections.FXCollections;
|
import javafx.collections.FXCollections;
|
||||||
import javafx.collections.ListChangeListener;
|
import javafx.collections.ListChangeListener;
|
||||||
import javafx.event.ActionEvent;
|
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
import javafx.scene.control.Button;
|
import javafx.scene.control.Button;
|
||||||
import javafx.scene.control.ComboBox;
|
import javafx.scene.control.ComboBox;
|
||||||
import javafx.scene.control.TableView;
|
import javafx.scene.control.TableView;
|
||||||
import ru.trader.core.Vendor;
|
|
||||||
import ru.trader.model.MarketModel;
|
import ru.trader.model.MarketModel;
|
||||||
import ru.trader.model.OfferDescModel;
|
import ru.trader.model.OfferDescModel;
|
||||||
import ru.trader.model.OrderModel;
|
import ru.trader.model.OrderModel;
|
||||||
@@ -16,9 +14,7 @@ import ru.trader.model.VendorModel;
|
|||||||
import ru.trader.view.support.NumberField;
|
import ru.trader.view.support.NumberField;
|
||||||
|
|
||||||
|
|
||||||
import java.awt.*;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
|
|
||||||
public class RoutersController {
|
public class RoutersController {
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ public class MarketModel {
|
|||||||
private final static Logger LOG = LoggerFactory.getLogger(MarketModel.class);
|
private final static Logger LOG = LoggerFactory.getLogger(MarketModel.class);
|
||||||
|
|
||||||
private final Market market;
|
private final Market market;
|
||||||
|
private final MarketAnalyzer analyzer;
|
||||||
|
|
||||||
private final Collection<ChangeMarketListener> listener = new ArrayList<>();
|
private final Collection<ChangeMarketListener> listener = new ArrayList<>();
|
||||||
|
|
||||||
@@ -41,6 +42,7 @@ public class MarketModel {
|
|||||||
|
|
||||||
public MarketModel(Market market) {
|
public MarketModel(Market market) {
|
||||||
this.market = market;
|
this.market = market;
|
||||||
|
analyzer = new MarketAnalyzer(market);
|
||||||
items = new SimpleListProperty<ItemDescModel>(BindingsHelper.observableList(market.getItems(), this::getItemDesc));
|
items = new SimpleListProperty<ItemDescModel>(BindingsHelper.observableList(market.getItems(), this::getItemDesc));
|
||||||
vendors = new SimpleListProperty<VendorModel>(BindingsHelper.observableList(market.get(), this::asModel));
|
vendors = new SimpleListProperty<VendorModel>(BindingsHelper.observableList(market.get(), this::asModel));
|
||||||
}
|
}
|
||||||
@@ -168,7 +170,7 @@ public class MarketModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public ObservableList<OrderModel> getTop(int limit, double balance, long max){
|
public ObservableList<OrderModel> getTop(int limit, double balance, long max){
|
||||||
return BindingsHelper.observableList(market.getTop(limit, balance, max), (o) -> {
|
return BindingsHelper.observableList(analyzer.getTop(limit, balance, max), (o) -> {
|
||||||
OrderModel model = new OrderModel(asOfferDescModel(o.getSell()), balance, max);
|
OrderModel model = new OrderModel(asOfferDescModel(o.getSell()), balance, max);
|
||||||
model.setBuyer(asModel(o.getBuy()));
|
model.setBuyer(asModel(o.getBuy()));
|
||||||
model.setCount(model.getMax());
|
model.setCount(model.getMax());
|
||||||
|
|||||||
@@ -42,8 +42,6 @@ public interface Market {
|
|||||||
|
|
||||||
void setChange(boolean change);
|
void setChange(boolean change);
|
||||||
|
|
||||||
Collection<Order> getTop(int limit, double balance, long max);
|
|
||||||
|
|
||||||
void updateName(Vendor vendor, String name);
|
void updateName(Vendor vendor, String name);
|
||||||
|
|
||||||
void updateName(Item item, String name);
|
void updateName(Item item, String name);
|
||||||
|
|||||||
87
core/src/main/java/ru/trader/core/MarketAnalyzer.java
Normal file
87
core/src/main/java/ru/trader/core/MarketAnalyzer.java
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
package ru.trader.core;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import ru.trader.graph.Graph;
|
||||||
|
import ru.trader.graph.Path;
|
||||||
|
import ru.trader.graph.PathRoute;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.TreeSet;
|
||||||
|
|
||||||
|
public class MarketAnalyzer {
|
||||||
|
private final static Logger LOG = LoggerFactory.getLogger(MarketAnalyzer.class);
|
||||||
|
|
||||||
|
private Market market;
|
||||||
|
private Graph<Vendor> graph;
|
||||||
|
private double stock;
|
||||||
|
private double maxDistance;
|
||||||
|
private int jumps;
|
||||||
|
|
||||||
|
|
||||||
|
public MarketAnalyzer(Market market) {
|
||||||
|
this.market = market;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<Order> getTop(int limit, double balance, long max){
|
||||||
|
LOG.debug("Get top {}", limit);
|
||||||
|
TreeSet<Order> top = new TreeSet<>();
|
||||||
|
for (Vendor vendor : market.get()) {
|
||||||
|
LOG.trace("Check vendor {}", vendor);
|
||||||
|
for (Offer sell : vendor.getAllSellOffers()) {
|
||||||
|
long count = Math.min(max, (long) Math.floor(balance / sell.getPrice()));
|
||||||
|
LOG.trace("Sell offer {}, count = {}", sell, count);
|
||||||
|
if (count == 0) continue;
|
||||||
|
Iterator<Offer> buyers = market.getStatBuy(sell.getItem()).getOffers().descendingIterator();
|
||||||
|
while (buyers.hasNext()){
|
||||||
|
Offer buy = buyers.next();
|
||||||
|
Order order = new Order(sell, buy, count);
|
||||||
|
LOG.trace("Buy offer {} profit = {}", buy, order.getProfit());
|
||||||
|
if (order.getProfit() <= 0 ) break;
|
||||||
|
if (top.size() == limit){
|
||||||
|
LOG.trace("Min order {}", top.first());
|
||||||
|
if (top.first().getProfit() < order.getProfit()) {
|
||||||
|
LOG.trace("Add to top");
|
||||||
|
top.add(order);
|
||||||
|
top.pollFirst();
|
||||||
|
} else {
|
||||||
|
LOG.trace("Is low profit, skip");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
top.add(order);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return top;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void rebuild(Vendor source){
|
||||||
|
graph = new Graph<>(source, market.get(), stock, maxDistance, true, jumps, PathRoute::new);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setSource(Vendor source){
|
||||||
|
if (graph == null || !graph.getRoot().equals(source))
|
||||||
|
rebuild(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<Path<Vendor>> getPaths(Vendor from, Vendor to){
|
||||||
|
setSource(from);
|
||||||
|
return graph.getPathsTo(to, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setStock(double stock) {
|
||||||
|
this.stock = stock;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMaxDistance(double maxDistance) {
|
||||||
|
this.maxDistance = maxDistance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setJumps(int jumps) {
|
||||||
|
this.jumps = jumps;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -169,39 +169,5 @@ public abstract class MarketSupport implements Market {
|
|||||||
this.change = change;
|
this.change = change;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Collection<Order> getTop(int limit, double balance, long max){
|
|
||||||
LOG.debug("Get top {}", limit);
|
|
||||||
TreeSet<Order> top = new TreeSet<>();
|
|
||||||
for (Vendor vendor : getVendors()) {
|
|
||||||
LOG.trace("Check vendor {}", vendor);
|
|
||||||
for (Offer sell : vendor.getAllSellOffers()) {
|
|
||||||
long count = Math.min(max, (long) Math.floor(balance / sell.getPrice()));
|
|
||||||
LOG.trace("Sell offer {}, count = {}", sell, count);
|
|
||||||
if (count == 0) continue;
|
|
||||||
Iterator<Offer> buyers = getStatBuy(sell.getItem()).getOffers().descendingIterator();
|
|
||||||
while (buyers.hasNext()){
|
|
||||||
Offer buy = buyers.next();
|
|
||||||
Order order = new Order(sell, buy, count);
|
|
||||||
LOG.trace("Buy offer {} profit = {}", buy, order.getProfit());
|
|
||||||
if (order.getProfit() <= 0 ) break;
|
|
||||||
if (top.size() == limit){
|
|
||||||
LOG.trace("Min order {}", top.first());
|
|
||||||
if (top.first().getProfit() < order.getProfit()) {
|
|
||||||
LOG.trace("Add to top");
|
|
||||||
top.add(order);
|
|
||||||
top.pollFirst();
|
|
||||||
} else {
|
|
||||||
LOG.trace("Is low profit, skip");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
top.add(order);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return top;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,10 +8,18 @@ public class Order implements Comparable<Order> {
|
|||||||
private Offer sell;
|
private Offer sell;
|
||||||
private Offer buy;
|
private Offer buy;
|
||||||
private double profit;
|
private double profit;
|
||||||
|
private long count;
|
||||||
|
|
||||||
|
public Order(Offer sell, Offer buy) {
|
||||||
|
this.sell = sell;
|
||||||
|
this.buy = buy;
|
||||||
|
this.profit = Double.NaN;
|
||||||
|
}
|
||||||
|
|
||||||
public Order(Offer sell, Offer buy, long count) {
|
public Order(Offer sell, Offer buy, long count) {
|
||||||
this.sell = sell;
|
this.sell = sell;
|
||||||
this.buy = buy;
|
this.buy = buy;
|
||||||
|
this.count = count;
|
||||||
this.profit = (buy.getPrice() - sell.getPrice()) * count;
|
this.profit = (buy.getPrice() - sell.getPrice()) * count;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -23,10 +31,31 @@ public class Order implements Comparable<Order> {
|
|||||||
return buy;
|
return buy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setCount(long count){
|
||||||
|
this.count = count;
|
||||||
|
this.profit = (buy.getPrice() - sell.getPrice()) * count;
|
||||||
|
}
|
||||||
|
|
||||||
public double getProfit(){
|
public double getProfit(){
|
||||||
return profit;
|
return profit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Order getCopy(long count){
|
||||||
|
return new Order(sell, buy, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getCount() {
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getDistance() {
|
||||||
|
return sell.getVendor().getDistance(buy.getVendor());
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isBuyer(Vendor buyer) {
|
||||||
|
return buy.getVendor().equals(buyer);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int compareTo(@NotNull Order order) {
|
public int compareTo(@NotNull Order order) {
|
||||||
Objects.requireNonNull(order, "Not compare with null");
|
Objects.requireNonNull(order, "Not compare with null");
|
||||||
@@ -56,11 +85,8 @@ public class Order implements Comparable<Order> {
|
|||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
int result;
|
int result;
|
||||||
long temp;
|
|
||||||
result = sell.hashCode();
|
result = sell.hashCode();
|
||||||
result = 31 * result + buy.hashCode();
|
result = 31 * result + buy.hashCode();
|
||||||
temp = Double.doubleToLongBits(profit);
|
|
||||||
result = 31 * result + (int) (temp ^ (temp >>> 32));
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,4 +99,5 @@ public class Order implements Comparable<Order> {
|
|||||||
sb.append('}');
|
sb.append('}');
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
25
core/src/main/java/ru/trader/core/Route.java
Normal file
25
core/src/main/java/ru/trader/core/Route.java
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
package ru.trader.core;
|
||||||
|
|
||||||
|
import ru.trader.graph.Path;
|
||||||
|
|
||||||
|
import java.util.LinkedList;
|
||||||
|
|
||||||
|
public class Route {
|
||||||
|
private double profit;
|
||||||
|
private double distance;
|
||||||
|
private final LinkedList<Order> orders = new LinkedList<>();
|
||||||
|
|
||||||
|
public Route() {
|
||||||
|
profit = 0;
|
||||||
|
distance = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void add(Order order){
|
||||||
|
orders.add(order);
|
||||||
|
profit += order.getProfit();
|
||||||
|
distance += order.getDistance();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
52
core/src/main/java/ru/trader/core/Ship.java
Normal file
52
core/src/main/java/ru/trader/core/Ship.java
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
package ru.trader.core;
|
||||||
|
|
||||||
|
public class Ship {
|
||||||
|
|
||||||
|
private double balance;
|
||||||
|
private long cargo;
|
||||||
|
private double engine;
|
||||||
|
private int jumps;
|
||||||
|
|
||||||
|
public Ship(double balance, long cargo, double engine, int jumps) {
|
||||||
|
this.balance = balance;
|
||||||
|
this.cargo = cargo;
|
||||||
|
this.engine = engine;
|
||||||
|
this.jumps = jumps;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Ship copyOf(Ship other){
|
||||||
|
return new Ship(other.balance, other.cargo, other.engine, other.jumps);
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getBalance() {
|
||||||
|
return balance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBalance(double balance) {
|
||||||
|
this.balance = balance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getCargo() {
|
||||||
|
return cargo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCargo(long cargo) {
|
||||||
|
this.cargo = cargo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getEngine() {
|
||||||
|
return engine;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEngine(double engine) {
|
||||||
|
this.engine = engine;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getJumps() {
|
||||||
|
return jumps;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setJumps(int jumps) {
|
||||||
|
this.jumps = jumps;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ package ru.trader.core;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
import ru.trader.graph.Connectable;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@@ -10,7 +11,7 @@ import java.util.List;
|
|||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public abstract class Vendor implements Comparable<Vendor> {
|
public abstract class Vendor implements Comparable<Vendor>, Connectable<Vendor> {
|
||||||
private final static Logger LOG = LoggerFactory.getLogger(Vendor.class);
|
private final static Logger LOG = LoggerFactory.getLogger(Vendor.class);
|
||||||
|
|
||||||
private String name;
|
private String name;
|
||||||
@@ -111,10 +112,16 @@ public abstract class Vendor implements Comparable<Vendor> {
|
|||||||
return name != null ? other.name != null ? name.compareTo(other.name) : -1 : 0;
|
return name != null ? other.name != null ? name.compareTo(other.name) : -1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public double getDistance(Vendor other){
|
public double getDistance(Vendor other){
|
||||||
return getDistance(other.x, other.y, other.z);
|
return getDistance(other.x, other.y, other.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canRefill() {
|
||||||
|
return !getAllSellOffers().isEmpty() || !getAllBuyOffers().isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
public double getDistance(double x, double y, double z){
|
public double getDistance(double x, double y, double z){
|
||||||
return Math.sqrt(Math.pow(x - this.x, 2) + Math.pow(y-this.y, 2) + Math.pow(z - this.z, 2));
|
return Math.sqrt(Math.pow(x - this.x, 2) + Math.pow(y-this.y, 2) + Math.pow(z - this.z, 2));
|
||||||
}
|
}
|
||||||
|
|||||||
9
core/src/main/java/ru/trader/graph/Connectable.java
Normal file
9
core/src/main/java/ru/trader/graph/Connectable.java
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
package ru.trader.graph;
|
||||||
|
|
||||||
|
public interface Connectable<T> {
|
||||||
|
|
||||||
|
public double getDistance(T other);
|
||||||
|
|
||||||
|
public boolean canRefill();
|
||||||
|
|
||||||
|
}
|
||||||
60
core/src/main/java/ru/trader/graph/Edge.java
Normal file
60
core/src/main/java/ru/trader/graph/Edge.java
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
package ru.trader.graph;
|
||||||
|
|
||||||
|
public class Edge<T extends Connectable<T>> {
|
||||||
|
protected double length;
|
||||||
|
protected final Vertex<T> target;
|
||||||
|
protected final Vertex<T> source;
|
||||||
|
|
||||||
|
public Edge(Vertex<T> source, T target) {
|
||||||
|
this(source, new Vertex<>(target));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Edge(Vertex<T> source, Vertex<T> target) {
|
||||||
|
this.target = target;
|
||||||
|
this.source = source;
|
||||||
|
this.length = source.getEntry().getDistance(target.getEntry());
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getLength(){
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isConnect(T other){
|
||||||
|
return target.getEntry().equals(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isConnect(Vertex<T> target){
|
||||||
|
return getTarget().equals(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vertex<T> getTarget(){
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vertex<T> getSource() {
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
|
||||||
|
Edge edge = (Edge) o;
|
||||||
|
|
||||||
|
return source.equals(edge.source) && target.equals(edge.target);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int result = target.hashCode();
|
||||||
|
result = 31 * result + source.hashCode();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return source.toString() + " -> " + target.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
182
core/src/main/java/ru/trader/graph/Graph.java
Normal file
182
core/src/main/java/ru/trader/graph/Graph.java
Normal file
@@ -0,0 +1,182 @@
|
|||||||
|
package ru.trader.graph;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
public class Graph<T extends Connectable<T>> {
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface PathConstructor<E extends Connectable<E>> {
|
||||||
|
Path<E> build(Vertex<E> source);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final static Logger LOG = LoggerFactory.getLogger(Graph.class);
|
||||||
|
|
||||||
|
private final Vertex<T> root;
|
||||||
|
private final HashMap<T,Vertex<T>> vertexes;
|
||||||
|
|
||||||
|
private final double stock;
|
||||||
|
private final double maxDistance;
|
||||||
|
private final boolean withRefill;
|
||||||
|
private final PathConstructor<T> pathFabric;
|
||||||
|
|
||||||
|
|
||||||
|
public Graph(T start, Collection<T> set, double stock, int maxDeep) {
|
||||||
|
this(start, set, stock, stock, false, maxDeep, Path::new);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Graph(T start, Collection<T> set, double stock, double maxDistance, int maxDeep) {
|
||||||
|
this(start, set, stock, maxDistance, true, maxDeep, Path::new);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Graph(T start, Collection<T> set, double stock, boolean withRefill, int maxDeep) {
|
||||||
|
this(start, set, stock, stock, withRefill, maxDeep, Path::new);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Graph(T start, Collection<T> set, double stock, boolean withRefill, int maxDeep, PathConstructor<T> pathFabric) {
|
||||||
|
this(start, set, stock, stock, withRefill, maxDeep, pathFabric);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Graph(T start, Collection<T> set, double stock, double maxDistance, boolean withRefill, int maxDeep, PathConstructor<T> pathFabric) {
|
||||||
|
this.maxDistance = maxDistance;
|
||||||
|
this.stock = stock;
|
||||||
|
this.withRefill = withRefill;
|
||||||
|
this.pathFabric = pathFabric;
|
||||||
|
root = new Vertex<>(start);
|
||||||
|
root.setLevel(maxDeep);
|
||||||
|
vertexes = new HashMap<>();
|
||||||
|
vertexes.put(root.getEntry(), root);
|
||||||
|
buildGraph(root, set, maxDeep-1, stock);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void buildGraph(Vertex<T> vertex, Collection<T> set, int deep, double limit) {
|
||||||
|
LOG.trace("Build graph from {}, limit {}, deep {}", vertex, limit, deep);
|
||||||
|
for (T entry : set) {
|
||||||
|
if (entry == vertex.getEntry()) continue;
|
||||||
|
double distance = vertex.getEntry().getDistance(entry);
|
||||||
|
if (distance <= this.maxDistance){
|
||||||
|
if (withRefill && distance > limit && !vertex.getEntry().canRefill()){
|
||||||
|
LOG.trace("Vertex {} is far away, {}", entry, distance);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Vertex<T> next = vertexes.get(entry);
|
||||||
|
if (next == null){
|
||||||
|
LOG.trace("Is new vertex");
|
||||||
|
next = new Vertex<>(entry);
|
||||||
|
vertexes.put(entry, next);
|
||||||
|
}
|
||||||
|
LOG.trace("Add edge from {} to {}", vertex, next);
|
||||||
|
Edge<T> edge = new Edge<>(vertex, next);
|
||||||
|
double nextLimit = withRefill ? limit - edge.getLength(): stock;
|
||||||
|
if (nextLimit < 0) {
|
||||||
|
LOG.trace("Refill");
|
||||||
|
nextLimit = stock - edge.getLength();
|
||||||
|
}
|
||||||
|
vertex.addEdge(edge);
|
||||||
|
// If level >= deep when vertex already added on upper deep
|
||||||
|
if (next.getLevel() < deep){
|
||||||
|
next.setLevel(vertex.getLevel()-1);
|
||||||
|
if (deep > 0){
|
||||||
|
buildGraph(next, set, deep-1, nextLimit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LOG.trace("End build graph from {} on deep {}", vertex, deep);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isAccessible(T entry){
|
||||||
|
return vertexes.containsKey(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vertex<T> getVertex(T entry){
|
||||||
|
return vertexes.get(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<Path<T>> getPathsTo(T entry, boolean all){
|
||||||
|
Vertex<T> target = getVertex(entry);
|
||||||
|
return findPaths(pathFabric.build(root), target, root.getLevel()-1, stock, all);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private Collection<Path<T>> findPaths(Path<T> head, Vertex<T> target, int deep, double limit, boolean all){
|
||||||
|
Collection<Path<T>> paths = new ArrayList<>();
|
||||||
|
if (target == null) return paths;
|
||||||
|
boolean found =false;
|
||||||
|
Vertex<T> source = head.getTarget();
|
||||||
|
LOG.trace("Find path to deep from {} to {}, deep {}, limit {}, head {}", source, target, deep, limit, head);
|
||||||
|
Edge<T> edge = source.getEdge(target);
|
||||||
|
if (edge != null ){
|
||||||
|
if (!(withRefill && Math.min(limit, maxDistance) < edge.getLength() && !source.getEntry().canRefill())){
|
||||||
|
found = true;
|
||||||
|
Path<T> path = head.connectTo(edge, limit < edge.getLength());
|
||||||
|
path.finish();
|
||||||
|
LOG.trace("Last edge find, add path {}", path);
|
||||||
|
paths.add(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((all || !found) && deep > 0 ){
|
||||||
|
if (source.getEdgesCount() > 0){
|
||||||
|
LOG.trace("Search around");
|
||||||
|
for (Edge<T> next : source.getEdges()) {
|
||||||
|
if (withRefill && Math.min(limit, maxDistance) < next.getLength() && !source.getEntry().canRefill()) continue;
|
||||||
|
if (head.contains(next)) continue;
|
||||||
|
// target already added if source consist edge
|
||||||
|
if (next.isConnect(target)) continue;
|
||||||
|
Path<T> path = head.connectTo(next, limit < next.getLength());
|
||||||
|
double nextLimit = withRefill ? limit - next.getLength(): stock;
|
||||||
|
// refill
|
||||||
|
if (nextLimit < 0 ) nextLimit = maxDistance - next.getLength();
|
||||||
|
paths.addAll(findPaths(path, target, deep - 1, nextLimit, all));
|
||||||
|
if (!all && !paths.isEmpty()) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return paths;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Path<T> getFastPathTo(T entry){
|
||||||
|
Vertex<T> target = getVertex(entry);
|
||||||
|
return findFastPath(pathFabric.build(root), target, target.getLevel()+1, stock);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Path<T> findFastPath(Path<T> head, Vertex<T> target, int deep, double limit) {
|
||||||
|
Vertex<T> source = head.getTarget();
|
||||||
|
LOG.trace("Find fast path from {} to {}, deep {}, limit {}, head {}", source, target, deep, limit, head);
|
||||||
|
if (deep == source.getLevel()){
|
||||||
|
for (Edge<T> next : source.getEdges()) {
|
||||||
|
if (withRefill && Math.min(limit, maxDistance) < next.getLength() && !source.getEntry().canRefill()) continue;
|
||||||
|
if (head.contains(next)) continue;
|
||||||
|
if (next.isConnect(target)) {
|
||||||
|
Path<T> path = head.connectTo(next, limit < next.getLength());
|
||||||
|
path.finish();
|
||||||
|
LOG.trace("Last edge find, path {}", path);
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (deep < source.getLevel()){
|
||||||
|
LOG.trace("Search around");
|
||||||
|
for (Edge<T> next : source.getEdges()) {
|
||||||
|
if (next.getTarget().getLevel() >= source.getLevel()) continue;
|
||||||
|
if (withRefill && Math.min(limit, maxDistance) < next.getLength() && !source.getEntry().canRefill()) continue;
|
||||||
|
Path<T> path = head.connectTo(next, limit < next.getLength());
|
||||||
|
double nextLimit = withRefill ? limit - next.getLength(): stock;
|
||||||
|
// refill
|
||||||
|
if (nextLimit < 0 ) nextLimit = stock - next.getLength();
|
||||||
|
Path<T> res = findFastPath(path, target, deep, nextLimit);
|
||||||
|
if (res != null) return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public T getRoot() {
|
||||||
|
return root.getEntry();
|
||||||
|
}
|
||||||
|
}
|
||||||
95
core/src/main/java/ru/trader/graph/Path.java
Normal file
95
core/src/main/java/ru/trader/graph/Path.java
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
package ru.trader.graph;
|
||||||
|
|
||||||
|
public class Path<T extends Connectable<T>> {
|
||||||
|
private final Path<T> head;
|
||||||
|
private final Vertex<T> target;
|
||||||
|
private boolean refill;
|
||||||
|
|
||||||
|
|
||||||
|
public Path(Vertex<T> source) {
|
||||||
|
this.head = null;
|
||||||
|
this.target = source;
|
||||||
|
this.refill = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Path(Path<T> head, Vertex<T> vertex, boolean refill) {
|
||||||
|
this.head = head;
|
||||||
|
this.target = vertex;
|
||||||
|
this.refill = refill;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Path<T> connectTo(Edge<T> edge, boolean refill){
|
||||||
|
return new Path<>(this, edge.getTarget(), refill);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void finish(){
|
||||||
|
finish(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void finish(Vertex<T> target){
|
||||||
|
if (!isRoot()){
|
||||||
|
head.finish(target);
|
||||||
|
if (target != head.target) head.finish();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isRoot(){
|
||||||
|
return head == null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (!(o instanceof Path)) return false;
|
||||||
|
|
||||||
|
Path path = (Path) o;
|
||||||
|
return (isRoot() ? path.isRoot() : head.equals(path.head)) && target.equals(path.target);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int result = head != null ? head.hashCode() : 0;
|
||||||
|
result = 31 * result + target.hashCode();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString(){
|
||||||
|
if (isRoot()) return target.getEntry().toString();
|
||||||
|
final StringBuilder sb = new StringBuilder(head.toString());
|
||||||
|
if (refill) sb.append("(R)");
|
||||||
|
sb.append(" -> ").append(target.getEntry());
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean contains(Edge<T> edge) {
|
||||||
|
return target.equals(edge.getTarget()) || (!isRoot() && head.contains(edge));
|
||||||
|
}
|
||||||
|
|
||||||
|
@SafeVarargs
|
||||||
|
public static <T extends Connectable<T>> Path<T> toPath(T... items){
|
||||||
|
T s = items[0];
|
||||||
|
Path<T> path = new Path<>(new Vertex<>(s));
|
||||||
|
for (int i = 1; i < items.length; i++) {
|
||||||
|
T t = items[i];
|
||||||
|
path = new Path<>(path, new Vertex<>(t), false);
|
||||||
|
s = t;
|
||||||
|
}
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vertex<T> getTarget() {
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isRefill(){
|
||||||
|
return refill;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Path<T> getHead(){
|
||||||
|
return head;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
96
core/src/main/java/ru/trader/graph/PathRoute.java
Normal file
96
core/src/main/java/ru/trader/graph/PathRoute.java
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
package ru.trader.graph;
|
||||||
|
|
||||||
|
import ru.trader.core.Offer;
|
||||||
|
import ru.trader.core.Order;
|
||||||
|
import ru.trader.core.Vendor;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
|
||||||
|
public class PathRoute extends Path<Vendor> {
|
||||||
|
private final ArrayList<Order> orders = new ArrayList<>();
|
||||||
|
|
||||||
|
public PathRoute(Vertex<Vendor> source) {
|
||||||
|
super(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected PathRoute(Path<Vendor> head, Vertex<Vendor> vertex, boolean refill) {
|
||||||
|
super(head, vertex, refill);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Path<Vendor> connectTo(Edge<Vendor> edge, boolean refill) {
|
||||||
|
return new PathRoute(this.getCopy(), edge.getTarget(), refill);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void finish(Vertex<Vendor> target) {
|
||||||
|
if (!isRoot()) {
|
||||||
|
if (!contains(target.getEntry())){
|
||||||
|
updateOrders(target.getEntry());
|
||||||
|
getHead().finish(target);
|
||||||
|
if (getHead().getTarget() != target) getHead().finish();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean contains(Vendor buyer){
|
||||||
|
for (Order order : orders) {
|
||||||
|
if (order.isBuyer(buyer)) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateOrders(Vendor buyer){
|
||||||
|
Vendor seller = getHead().getTarget().getEntry();
|
||||||
|
for (Offer sell : seller.getAllSellOffers()) {
|
||||||
|
Offer buy = buyer.getBuy(sell.getItem());
|
||||||
|
if (buy != null) orders.add(new Order(sell, buy));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<Order> getOrders() {
|
||||||
|
return orders;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (Order order : orders) {
|
||||||
|
if (sb.length() > 0) sb.append(", ");
|
||||||
|
sb.append(order.getBuy().getItem());
|
||||||
|
sb.append(" (").append(order.getBuy().getVendor()).append(") ");
|
||||||
|
}
|
||||||
|
String o = sb.toString();
|
||||||
|
sb = new StringBuilder();
|
||||||
|
if (isRoot()){
|
||||||
|
sb.append(getTarget().getEntry());
|
||||||
|
if (o.length()>0) sb.append(" (").append(o).append(") ");
|
||||||
|
} else {
|
||||||
|
sb.append(getHead().toString());
|
||||||
|
if (isRefill()) sb.append("(R)");
|
||||||
|
if (o.length()>0) sb.append(" (").append(o).append(") ");
|
||||||
|
sb.append(" -> ").append(getTarget().getEntry());
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Path<Vendor> getCopy(){
|
||||||
|
Path<Vendor> res;
|
||||||
|
LinkedList<Path<Vendor>> v = new LinkedList<>();
|
||||||
|
Path<Vendor> p = this;
|
||||||
|
while (!p.isRoot()){
|
||||||
|
v.add(p);
|
||||||
|
p = p.getHead();
|
||||||
|
}
|
||||||
|
res = p;
|
||||||
|
Iterator<Path<Vendor>> it = v.descendingIterator();
|
||||||
|
while (it.hasNext()){
|
||||||
|
p = it.next();
|
||||||
|
res = new PathRoute(res, p.getTarget(), p.isRefill());
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
83
core/src/main/java/ru/trader/graph/Vertex.java
Normal file
83
core/src/main/java/ru/trader/graph/Vertex.java
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
package ru.trader.graph;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.HashSet;
|
||||||
|
|
||||||
|
public class Vertex<T extends Connectable<T>> {
|
||||||
|
private final ArrayList<Edge<T>> edges = new ArrayList<>();
|
||||||
|
private final T entry;
|
||||||
|
private int level = -1;
|
||||||
|
|
||||||
|
public Vertex(T entry) {
|
||||||
|
this.entry = entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
public T getEntry() {
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isConnected(Vertex<T> other){
|
||||||
|
return isConnected(other.entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isConnected(T other){
|
||||||
|
return edges.stream().anyMatch((e) -> e.isConnect(other));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addEdge(Edge<T> edge){
|
||||||
|
if (edges.contains(edge)) return;
|
||||||
|
edges.add(edge);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<Edge<T>> getEdges() {
|
||||||
|
return edges;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
Vertex vertex = (Vertex) o;
|
||||||
|
return entry.equals(vertex.entry);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return entry.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sortEdges(Comparator<Edge> comparator){
|
||||||
|
edges.sort(comparator);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLevel() {
|
||||||
|
return level;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLevel(int level) {
|
||||||
|
this.level = level;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getEdgesCount(){
|
||||||
|
return edges.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
final StringBuilder sb = new StringBuilder("Vertex{");
|
||||||
|
sb.append(entry);
|
||||||
|
sb.append(", lvl=").append(level);
|
||||||
|
sb.append('}');
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Edge<T> getEdge(Vertex<T> target) {
|
||||||
|
for (Edge<T> edge : edges) {
|
||||||
|
if (edge.isConnect(target)) return edge;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,9 +3,13 @@ package ru.trader.core;
|
|||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
|
||||||
public class ItemStatTest extends Assert {
|
public class ItemStatTest extends Assert {
|
||||||
|
private final static Logger LOG = LoggerFactory.getLogger(ItemStatTest.class);
|
||||||
|
|
||||||
private final static Item ITEM1 = new Item("Item1");
|
private final static Item ITEM1 = new Item("Item1");
|
||||||
|
|
||||||
|
|
||||||
@@ -29,12 +33,14 @@ public class ItemStatTest extends Assert {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSell(){
|
public void testSell(){
|
||||||
|
LOG.info("Start sell test");
|
||||||
assertEquals(itemSellStat.getAvg(), (10+20+30+40)/4, 0);
|
assertEquals(itemSellStat.getAvg(), (10+20+30+40)/4, 0);
|
||||||
assertEquals(itemSellStat.getBest().getPrice(), 10d, 0);
|
assertEquals(itemSellStat.getBest().getPrice(), 10d, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testBuy(){
|
public void testBuy(){
|
||||||
|
LOG.info("Start buy test");
|
||||||
assertEquals(itemBuyStat.getAvg(), (100+200+300+400)/4, 0);
|
assertEquals(itemBuyStat.getAvg(), (100+200+300+400)/4, 0);
|
||||||
assertEquals(itemBuyStat.getBest().getPrice(), 400d, 0);
|
assertEquals(itemBuyStat.getBest().getPrice(), 400d, 0);
|
||||||
}
|
}
|
||||||
|
|||||||
192
core/src/test/java/ru/trader/core/MarketAnalyzerTest.java
Normal file
192
core/src/test/java/ru/trader/core/MarketAnalyzerTest.java
Normal file
@@ -0,0 +1,192 @@
|
|||||||
|
package ru.trader.core;
|
||||||
|
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import ru.trader.TestUtil;
|
||||||
|
import ru.trader.graph.Path;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
public class MarketAnalyzerTest extends Assert {
|
||||||
|
private final static Logger LOG = LoggerFactory.getLogger(MarketAnalyzerTest.class);
|
||||||
|
|
||||||
|
private static Market market = new SimpleMarket();
|
||||||
|
private static Vendor v1;
|
||||||
|
private static Vendor v2;
|
||||||
|
private static Vendor v3;
|
||||||
|
private static Vendor v4;
|
||||||
|
private static Vendor v5;
|
||||||
|
private static Vendor v6;
|
||||||
|
private static Vendor v7;
|
||||||
|
private static Vendor v8;
|
||||||
|
private static Vendor v9;
|
||||||
|
private static Vendor v10;
|
||||||
|
private static Vendor v11;
|
||||||
|
private static Item ITEM1 = new Item("ITEM1");
|
||||||
|
private static Item ITEM2 = new Item("ITEM2");
|
||||||
|
private static Item ITEM3 = new Item("ITEM3");
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
v1 = new SimpleVendor("v1_x0y0z0");
|
||||||
|
v2 = new SimpleVendor("v2_x1y0z0");
|
||||||
|
v3 = new SimpleVendor("v3_x0y1z0");
|
||||||
|
v4 = new SimpleVendor("v4_x0y0z1");
|
||||||
|
v5 = new SimpleVendor("v5_x1y1z0");
|
||||||
|
|
||||||
|
v6 = new SimpleVendor("v6_x110y100z100");
|
||||||
|
v7 = new SimpleVendor("v7_x115y100z100");
|
||||||
|
v8 = new SimpleVendor("v8_x105y105z100");
|
||||||
|
v9 = new SimpleVendor("v9_x100y115z100");
|
||||||
|
v10 = new SimpleVendor("v10_x100y100z100");
|
||||||
|
v11 = new SimpleVendor("v11_x105y105z105");
|
||||||
|
|
||||||
|
v1.setX(0); v1.setY(0); v1.setZ(0);
|
||||||
|
v2.setX(1); v2.setY(0); v2.setZ(0);
|
||||||
|
v3.setX(0); v3.setY(1); v3.setZ(0);
|
||||||
|
v4.setX(0); v4.setY(0); v4.setZ(1);
|
||||||
|
v5.setX(1); v5.setY(1); v5.setZ(0);
|
||||||
|
v6.setX(110); v6.setY(100); v6.setZ(100);
|
||||||
|
v7.setX(115); v7.setY(100); v7.setZ(100);
|
||||||
|
v8.setX(105); v8.setY(105); v8.setZ(100);
|
||||||
|
v9.setX(100); v9.setY(115); v9.setZ(100);
|
||||||
|
v10.setX(100); v10.setY(100); v10.setZ(100);
|
||||||
|
v11.setX(105); v11.setY(105); v11.setZ(105);
|
||||||
|
|
||||||
|
market.add(v1);
|
||||||
|
market.add(v2);
|
||||||
|
market.add(v3);
|
||||||
|
market.add(v4);
|
||||||
|
market.add(v5);
|
||||||
|
market.add(v6);
|
||||||
|
market.add(v7);
|
||||||
|
market.add(v8);
|
||||||
|
market.add(v9);
|
||||||
|
market.add(v10);
|
||||||
|
market.add(v11);
|
||||||
|
|
||||||
|
market.add(v6, new Offer(OFFER_TYPE.SELL, ITEM1, 100));
|
||||||
|
market.add(v7, new Offer(OFFER_TYPE.SELL, ITEM1, 100));
|
||||||
|
market.add(v9, new Offer(OFFER_TYPE.SELL, ITEM1, 100));
|
||||||
|
market.add(v10, new Offer(OFFER_TYPE.SELL, ITEM1, 100));
|
||||||
|
market.add(v6, new Offer(OFFER_TYPE.BUY, ITEM1, 50));
|
||||||
|
market.add(v7, new Offer(OFFER_TYPE.BUY, ITEM1, 120));
|
||||||
|
market.add(v9, new Offer(OFFER_TYPE.BUY, ITEM1, 200));
|
||||||
|
market.add(v10, new Offer(OFFER_TYPE.BUY, ITEM1, 150));
|
||||||
|
market.add(v9, new Offer(OFFER_TYPE.SELL, ITEM2, 100));
|
||||||
|
market.add(v6, new Offer(OFFER_TYPE.BUY, ITEM2, 140));
|
||||||
|
market.add(v7, new Offer(OFFER_TYPE.SELL, ITEM3, 154));
|
||||||
|
market.add(v10, new Offer(OFFER_TYPE.BUY, ITEM3, 140));
|
||||||
|
market.add(v11, new Offer(OFFER_TYPE.BUY, ITEM3, 500));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPaths() throws Exception {
|
||||||
|
LOG.info("Start paths test");
|
||||||
|
MarketAnalyzer analyzer = new MarketAnalyzer(market);
|
||||||
|
analyzer.setJumps(5);analyzer.setMaxDistance(1);analyzer.setStock(1);
|
||||||
|
|
||||||
|
Collection<Path<Vendor>> paths = analyzer.getPaths(v1, v2);
|
||||||
|
TestUtil.assertCollectionEquals(paths, Path.toPath(v1, v2));
|
||||||
|
|
||||||
|
paths = analyzer.getPaths(v1, v3);
|
||||||
|
TestUtil.assertCollectionEquals(paths, Path.toPath(v1, v3));
|
||||||
|
|
||||||
|
paths = analyzer.getPaths(v1, v4);
|
||||||
|
TestUtil.assertCollectionEquals(paths, Path.toPath(v1, v4));
|
||||||
|
|
||||||
|
paths = analyzer.getPaths(v1, v5);
|
||||||
|
assertTrue(paths.isEmpty());
|
||||||
|
|
||||||
|
paths = analyzer.getPaths(v2, v5);
|
||||||
|
TestUtil.assertCollectionEquals(paths, Path.toPath(v2, v5));
|
||||||
|
|
||||||
|
paths = analyzer.getPaths(v4, v3);
|
||||||
|
assertTrue(paths.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@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.setStock(2);
|
||||||
|
|
||||||
|
Collection<Path<Vendor>> paths = analyzer.getPaths(v1, v2);
|
||||||
|
TestUtil.assertCollectionContainAll(paths, Path.toPath(v1, v2));
|
||||||
|
|
||||||
|
paths = analyzer.getPaths(v1, v3);
|
||||||
|
TestUtil.assertCollectionContainAll(paths, Path.toPath(v1, v3));
|
||||||
|
|
||||||
|
paths = analyzer.getPaths(v1, v4);
|
||||||
|
TestUtil.assertCollectionContainAll(paths, Path.toPath(v1, v4));
|
||||||
|
|
||||||
|
paths = analyzer.getPaths(v1, v5);
|
||||||
|
TestUtil.assertCollectionContainAll(paths, Path.toPath(v1, v2, v5), Path.toPath(v1, v3, v5));
|
||||||
|
|
||||||
|
paths = analyzer.getPaths(v2, v5);
|
||||||
|
TestUtil.assertCollectionContainAll(paths, Path.toPath(v2, v5));
|
||||||
|
|
||||||
|
paths = analyzer.getPaths(v4, v3);
|
||||||
|
TestUtil.assertCollectionContainAll(paths, Path.toPath(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.setStock(15);
|
||||||
|
|
||||||
|
Collection<Path<Vendor>> paths = analyzer.getPaths(v10, v6);
|
||||||
|
TestUtil.assertCollectionContainAll(paths, Path.toPath(v10, v6), Path.toPath(v10, v11, v6),
|
||||||
|
Path.toPath(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)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@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.setStock(15);
|
||||||
|
|
||||||
|
Collection<Path<Vendor>> paths = analyzer.getPaths(v10, v6);
|
||||||
|
TestUtil.assertCollectionContainAll(paths, Path.toPath(v10, v6), Path.toPath(v10, v11, v6),
|
||||||
|
Path.toPath(v10, v8, v6), Path.toPath(v10, v8, v11, 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)
|
||||||
|
);
|
||||||
|
|
||||||
|
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));
|
||||||
|
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() throws Exception {
|
||||||
|
market = new SimpleMarket();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,8 +3,12 @@ package ru.trader.core;
|
|||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
public class MarketTest1 extends Assert {
|
public class MarketTest1 extends Assert {
|
||||||
|
private final static Logger LOG = LoggerFactory.getLogger(MarketTest1.class);
|
||||||
|
|
||||||
private final static Item ITEM1 = new Item("Item1");
|
private final static Item ITEM1 = new Item("Item1");
|
||||||
private final static Item ITEM2 = new Item("Item2");
|
private final static Item ITEM2 = new Item("Item2");
|
||||||
private final static Item ITEM3 = new Item("Item3");
|
private final static Item ITEM3 = new Item("Item3");
|
||||||
@@ -64,6 +68,7 @@ public class MarketTest1 extends Assert {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testBestSell(){
|
public void testBestSell(){
|
||||||
|
LOG.info("Start best sell test");
|
||||||
Offer test = market.getStatSell(ITEM1).getBest();
|
Offer test = market.getStatSell(ITEM1).getBest();
|
||||||
assertEquals(test, bestSellOffer1);
|
assertEquals(test, bestSellOffer1);
|
||||||
test = market.getStatSell(ITEM2).getBest();
|
test = market.getStatSell(ITEM2).getBest();
|
||||||
@@ -74,6 +79,7 @@ public class MarketTest1 extends Assert {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testBestBuy(){
|
public void testBestBuy(){
|
||||||
|
LOG.info("Start best buy test");
|
||||||
Offer test = market.getStatBuy(ITEM1).getBest();
|
Offer test = market.getStatBuy(ITEM1).getBest();
|
||||||
assertEquals(test, bestBuyOffer1);
|
assertEquals(test, bestBuyOffer1);
|
||||||
test = market.getStatBuy(ITEM2).getBest();
|
test = market.getStatBuy(ITEM2).getBest();
|
||||||
|
|||||||
@@ -3,9 +3,13 @@ package ru.trader.core;
|
|||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
|
||||||
public class VendorTest extends Assert {
|
public class VendorTest extends Assert {
|
||||||
|
private final static Logger LOG = LoggerFactory.getLogger(VendorTest.class);
|
||||||
|
|
||||||
private final static Item ITEM1 = new Item("Item1");
|
private final static Item ITEM1 = new Item("Item1");
|
||||||
private final static Item ITEM2 = new Item("Item2");
|
private final static Item ITEM2 = new Item("Item2");
|
||||||
private final static Offer SELL_OFFER = new Offer(OFFER_TYPE.SELL, ITEM1, 10);
|
private final static Offer SELL_OFFER = new Offer(OFFER_TYPE.SELL, ITEM1, 10);
|
||||||
@@ -24,6 +28,7 @@ public class VendorTest extends Assert {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAddSellOffer(){
|
public void testAddSellOffer(){
|
||||||
|
LOG.info("Start add sell offer test");
|
||||||
final Iterable<Offer> offers = sellVendor.getAllSellOffers();
|
final Iterable<Offer> offers = sellVendor.getAllSellOffers();
|
||||||
Offer test = offers.iterator().next();
|
Offer test = offers.iterator().next();
|
||||||
assertEquals(test, SELL_OFFER);
|
assertEquals(test, SELL_OFFER);
|
||||||
@@ -31,18 +36,21 @@ public class VendorTest extends Assert {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAddSellOffer2(){
|
public void testAddSellOffer2(){
|
||||||
|
LOG.info("Start add sell offer test2");
|
||||||
final Iterable<Offer> offers = sellVendor.getAllBuyOffers();
|
final Iterable<Offer> offers = sellVendor.getAllBuyOffers();
|
||||||
assertFalse(offers.iterator().hasNext());
|
assertFalse(offers.iterator().hasNext());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAddBuyOffer(){
|
public void testAddBuyOffer(){
|
||||||
|
LOG.info("Start add buy offer test");
|
||||||
final Iterable<Offer> offers = buyVendor.getAllSellOffers();
|
final Iterable<Offer> offers = buyVendor.getAllSellOffers();
|
||||||
assertFalse(offers.iterator().hasNext());
|
assertFalse(offers.iterator().hasNext());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAddBuyOffer2(){
|
public void testAddBuyOffer2(){
|
||||||
|
LOG.info("Start add buy offer test2");
|
||||||
final Iterable<Offer> offers = buyVendor.getAllBuyOffers();
|
final Iterable<Offer> offers = buyVendor.getAllBuyOffers();
|
||||||
Offer test = offers.iterator().next();
|
Offer test = offers.iterator().next();
|
||||||
assertEquals(test, BUY_OFFER);
|
assertEquals(test, BUY_OFFER);
|
||||||
@@ -50,36 +58,42 @@ public class VendorTest extends Assert {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetSellOfferOnSellVendor(){
|
public void testGetSellOfferOnSellVendor(){
|
||||||
|
LOG.info("Start get sell offer from sell vendor test");
|
||||||
Offer test = sellVendor.getSell(ITEM1);
|
Offer test = sellVendor.getSell(ITEM1);
|
||||||
assertEquals(test, SELL_OFFER);
|
assertEquals(test, SELL_OFFER);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetSellOfferOnBuyVendor(){
|
public void testGetSellOfferOnBuyVendor(){
|
||||||
|
LOG.info("Start get sell offer from buy vendor test");
|
||||||
Offer test = buyVendor.getSell(ITEM1);
|
Offer test = buyVendor.getSell(ITEM1);
|
||||||
assertNull(test);
|
assertNull(test);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetWrongItemSellOfferOnSellVendor(){
|
public void testGetWrongItemSellOfferOnSellVendor(){
|
||||||
|
LOG.info("Start get wrong item from sell vendor test");
|
||||||
Offer test = buyVendor.getSell(ITEM2);
|
Offer test = buyVendor.getSell(ITEM2);
|
||||||
assertNull(test);
|
assertNull(test);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetBuyOfferOnSellVendor(){
|
public void testGetBuyOfferOnSellVendor(){
|
||||||
|
LOG.info("Start get buy offer from sell vendor test");
|
||||||
Offer test = sellVendor.getBuy(ITEM1);
|
Offer test = sellVendor.getBuy(ITEM1);
|
||||||
assertNull(test);
|
assertNull(test);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetBuyOffersOnBuyVendor(){
|
public void testGetBuyOffersOnBuyVendor(){
|
||||||
|
LOG.info("Start get buy offer from buy vendor test");
|
||||||
Offer test = buyVendor.getBuy(ITEM1);
|
Offer test = buyVendor.getBuy(ITEM1);
|
||||||
assertEquals(test, BUY_OFFER);
|
assertEquals(test, BUY_OFFER);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetWrongItemBuyOfferOnBuyVendor(){
|
public void testGetWrongItemBuyOfferOnBuyVendor(){
|
||||||
|
LOG.info("Start get wrong item from buy vendor test");
|
||||||
Offer test = sellVendor.getBuy(ITEM2);
|
Offer test = sellVendor.getBuy(ITEM2);
|
||||||
assertNull(test);
|
assertNull(test);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,11 +3,15 @@ package ru.trader.core;
|
|||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
import ru.trader.TestUtil;
|
import ru.trader.TestUtil;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
public class VendorTest2 extends Assert {
|
public class VendorTest2 extends Assert {
|
||||||
|
private final static Logger LOG = LoggerFactory.getLogger(VendorTest2.class);
|
||||||
|
|
||||||
private final static Item ITEM1 = new Item("Item1");
|
private final static Item ITEM1 = new Item("Item1");
|
||||||
private final static Item ITEM2 = new Item("Item2");
|
private final static Item ITEM2 = new Item("Item2");
|
||||||
private final static Item ITEM3 = new Item("Item3");
|
private final static Item ITEM3 = new Item("Item3");
|
||||||
@@ -42,24 +46,28 @@ public class VendorTest2 extends Assert {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetSellOffer(){
|
public void testGetSellOffer(){
|
||||||
|
LOG.info("Start get sell offer test");
|
||||||
final Offer test = sellVendor.getSell(ITEM1);
|
final Offer test = sellVendor.getSell(ITEM1);
|
||||||
assertEquals(test, DUBLE_SELL_OFFER1);
|
assertEquals(test, DUBLE_SELL_OFFER1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetBuyOffer(){
|
public void testGetBuyOffer(){
|
||||||
|
LOG.info("Start get buy offer test");
|
||||||
final Offer test = buyVendor.getBuy(ITEM1);
|
final Offer test = buyVendor.getBuy(ITEM1);
|
||||||
assertEquals(test, DUBLE_BUY_OFFER1);
|
assertEquals(test, DUBLE_BUY_OFFER1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetAllSellOffer(){
|
public void testGetAllSellOffer(){
|
||||||
|
LOG.info("Start get all sell offer test");
|
||||||
final Collection<Offer> test = sellVendor.getAllSellOffers();
|
final Collection<Offer> test = sellVendor.getAllSellOffers();
|
||||||
TestUtil.assertCollectionContainAll(test, DUBLE_SELL_OFFER1, SELL_OFFER2, SELL_OFFER3);
|
TestUtil.assertCollectionContainAll(test, DUBLE_SELL_OFFER1, SELL_OFFER2, SELL_OFFER3);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetAllBuyOffer(){
|
public void testGetAllBuyOffer(){
|
||||||
|
LOG.info("Start get all buy offer test");
|
||||||
final Collection<Offer> test = buyVendor.getAllBuyOffers();
|
final Collection<Offer> test = buyVendor.getAllBuyOffers();
|
||||||
TestUtil.assertCollectionContainAll(test, DUBLE_BUY_OFFER1, BUY_OFFER3, BUY_OFFER2);
|
TestUtil.assertCollectionContainAll(test, DUBLE_BUY_OFFER1, BUY_OFFER3, BUY_OFFER2);
|
||||||
}
|
}
|
||||||
|
|||||||
314
core/src/test/java/ru/trader/graph/GraphTest.java
Normal file
314
core/src/test/java/ru/trader/graph/GraphTest.java
Normal file
@@ -0,0 +1,314 @@
|
|||||||
|
package ru.trader.graph;
|
||||||
|
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import ru.trader.TestUtil;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
public class GraphTest extends Assert {
|
||||||
|
private final static Logger LOG = LoggerFactory.getLogger(GraphTest.class);
|
||||||
|
|
||||||
|
private final static ArrayList<Point> entrys = new ArrayList<>();
|
||||||
|
private final static Point x1 = new Point("x1",-40);
|
||||||
|
private final static Point x2 = new Point("x2",-20);
|
||||||
|
private final static Point x3 = new Point("x3",-10, true);
|
||||||
|
private final static Point x4 = new Point("x4",-5, true);
|
||||||
|
private final static Point x5 = new Point("x5",0);
|
||||||
|
private final static Point x6 = new Point("x6",5);
|
||||||
|
private final static Point x7 = new Point("x7",20);
|
||||||
|
private final static Point x8 = new Point("x8",30);
|
||||||
|
private final static Point x9 = new Point("x9",40);
|
||||||
|
private final static Point x10 = new Point("x10",50);
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
entrys.add(x1);
|
||||||
|
entrys.add(x2);
|
||||||
|
entrys.add(x3);
|
||||||
|
entrys.add(x4);
|
||||||
|
entrys.add(x5);
|
||||||
|
entrys.add(x6);
|
||||||
|
entrys.add(x7);
|
||||||
|
entrys.add(x8);
|
||||||
|
entrys.add(x9);
|
||||||
|
entrys.add(x10);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBuild0() throws Exception {
|
||||||
|
LOG.info("Start graph build test0");
|
||||||
|
|
||||||
|
Graph<Point> graph = new Graph<>(x5, entrys, 4.9, 10);
|
||||||
|
// x5
|
||||||
|
assertFalse(graph.isAccessible(x1));
|
||||||
|
assertFalse(graph.isAccessible(x2));
|
||||||
|
assertFalse(graph.isAccessible(x3));
|
||||||
|
assertFalse(graph.isAccessible(x4));
|
||||||
|
assertTrue(graph.isAccessible(x5));
|
||||||
|
assertFalse(graph.isAccessible(x6));
|
||||||
|
assertFalse(graph.isAccessible(x7));
|
||||||
|
assertFalse(graph.isAccessible(x8));
|
||||||
|
assertFalse(graph.isAccessible(x9));
|
||||||
|
assertFalse(graph.isAccessible(x10));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBuild1() throws Exception {
|
||||||
|
LOG.info("Start graph build test1");
|
||||||
|
Graph<Point> graph = new Graph<>(x5, entrys, 5.1, true, 2);
|
||||||
|
// x5 <-> x4 <-refill-> x3, x5 -> x6
|
||||||
|
assertFalse(graph.isAccessible(x1));
|
||||||
|
assertFalse(graph.isAccessible(x2));
|
||||||
|
assertTrue(graph.isAccessible(x3));
|
||||||
|
assertTrue(graph.isAccessible(x4));
|
||||||
|
assertTrue(graph.isAccessible(x5));
|
||||||
|
assertTrue(graph.isAccessible(x6));
|
||||||
|
assertFalse(graph.isAccessible(x7));
|
||||||
|
assertFalse(graph.isAccessible(x8));
|
||||||
|
assertFalse(graph.isAccessible(x9));
|
||||||
|
assertFalse(graph.isAccessible(x10));
|
||||||
|
|
||||||
|
Vertex<Point> x = graph.getVertex(x5);
|
||||||
|
// x5 -> x4, x5 -> x6
|
||||||
|
checkEdges(x, new Point[]{x4, x6}, new Point[]{x1, x2, x3, x7, x8, x9, x10});
|
||||||
|
// x4 -> x5
|
||||||
|
x = graph.getVertex(x4);
|
||||||
|
checkEdges(x, new Point[]{x5, x3}, new Point[]{x1, x2, x6, x7, x8, x9, x10});
|
||||||
|
// x6 <- x5
|
||||||
|
x = graph.getVertex(x6);
|
||||||
|
checkEdges(x, new Point[]{}, new Point[]{x1, x2, x3, x4, x5, x7, x8, x9, x10});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkEdges(Vertex<Point> vertex, Point[] trueEdge, Point[] falseEdge){
|
||||||
|
for (Point point : trueEdge) {
|
||||||
|
assertTrue(String.format("%s must have edge to %s", vertex, point), vertex.isConnected(point));
|
||||||
|
}
|
||||||
|
for (Point point : falseEdge) {
|
||||||
|
assertFalse(String.format("%s must not have edge to %s", vertex, point), vertex.isConnected(point));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBuild2() throws Exception {
|
||||||
|
LOG.info("Start graph build test2");
|
||||||
|
Graph<Point> graph = new Graph<>(x5, entrys, 5.1, 3);
|
||||||
|
// x5 <-> x4 <-> x3, x5 <-> x6
|
||||||
|
assertFalse(graph.isAccessible(x1));
|
||||||
|
assertFalse(graph.isAccessible(x2));
|
||||||
|
assertTrue(graph.isAccessible(x3));
|
||||||
|
assertTrue(graph.isAccessible(x4));
|
||||||
|
assertTrue(graph.isAccessible(x5));
|
||||||
|
assertTrue(graph.isAccessible(x6));
|
||||||
|
assertFalse(graph.isAccessible(x7));
|
||||||
|
assertFalse(graph.isAccessible(x8));
|
||||||
|
assertFalse(graph.isAccessible(x9));
|
||||||
|
assertFalse(graph.isAccessible(x10));
|
||||||
|
|
||||||
|
Vertex<Point> x = graph.getVertex(x5);
|
||||||
|
// x5 -> x4, x5 -> x6
|
||||||
|
checkEdges(x, new Point[]{x4, x6}, new Point[]{x1, x2, x3, x7, x8, x9, x10});
|
||||||
|
// x3 -> x4
|
||||||
|
x = graph.getVertex(x3);
|
||||||
|
checkEdges(x, new Point[]{x4}, new Point[]{x1, x2, x5, x6, x7, x8, x9, x10});
|
||||||
|
// x4 -> x5, x4 -> x3
|
||||||
|
x = graph.getVertex(x4);
|
||||||
|
checkEdges(x, new Point[]{x3, x5}, new Point[]{x1, x2, x6, x7, x8, x9, x10});
|
||||||
|
// x6 -> x5
|
||||||
|
x = graph.getVertex(x6);
|
||||||
|
checkEdges(x, new Point[]{x5}, new Point[]{x1, x2, x3, x4, x7, x8, x9, x10});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBuild3() throws Exception {
|
||||||
|
LOG.info("Start graph build test3");
|
||||||
|
Graph<Point> graph = new Graph<>(x5, entrys, 5.1, 3);
|
||||||
|
// x5 <-> x4 <-> x3, x5 <-> x6
|
||||||
|
assertFalse(graph.isAccessible(x1));
|
||||||
|
assertFalse(graph.isAccessible(x2));
|
||||||
|
assertTrue(graph.isAccessible(x3));
|
||||||
|
assertTrue(graph.isAccessible(x4));
|
||||||
|
assertTrue(graph.isAccessible(x5));
|
||||||
|
assertTrue(graph.isAccessible(x6));
|
||||||
|
assertFalse(graph.isAccessible(x7));
|
||||||
|
assertFalse(graph.isAccessible(x8));
|
||||||
|
assertFalse(graph.isAccessible(x9));
|
||||||
|
assertFalse(graph.isAccessible(x10));
|
||||||
|
|
||||||
|
Vertex<Point> x = graph.getVertex(x5);
|
||||||
|
// x5 -> x4, x5 -> x6
|
||||||
|
checkEdges(x, new Point[]{x4, x6}, new Point[]{x1, x2, x3, x7, x8, x9, x10});
|
||||||
|
// x3 -> x4
|
||||||
|
x = graph.getVertex(x3);
|
||||||
|
checkEdges(x, new Point[]{x4}, new Point[]{x1, x2, x5, x6, x7, x8, x9, x10});
|
||||||
|
// x4 -> x5, x4 -> x3
|
||||||
|
x = graph.getVertex(x4);
|
||||||
|
checkEdges(x, new Point[]{x3, x5}, new Point[]{x1, x2, x6, x7, x8, x9, x10});
|
||||||
|
// x6 -> x5
|
||||||
|
x = graph.getVertex(x6);
|
||||||
|
checkEdges(x, new Point[]{x5}, new Point[]{x1, x2, x3, x4, x7, x8, x9, x10});
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBuild4() throws Exception {
|
||||||
|
LOG.info("Start graph build test4");
|
||||||
|
Graph<Point> graph = new Graph<>(x5, entrys, 15.1, 3);
|
||||||
|
// x5 <-> x4 <-> x3 -> x2, x5 <-> x6 <-> x7 -> x8
|
||||||
|
// x5 <-> x3, x5 <-> x4 <-> x2, x3 <-> x6, x4 <-> x6
|
||||||
|
assertFalse(graph.isAccessible(x1));
|
||||||
|
assertTrue(graph.isAccessible(x2));
|
||||||
|
assertTrue(graph.isAccessible(x3));
|
||||||
|
assertTrue(graph.isAccessible(x4));
|
||||||
|
assertTrue(graph.isAccessible(x5));
|
||||||
|
assertTrue(graph.isAccessible(x6));
|
||||||
|
assertTrue(graph.isAccessible(x7));
|
||||||
|
assertTrue(graph.isAccessible(x8));
|
||||||
|
assertFalse(graph.isAccessible(x9));
|
||||||
|
assertFalse(graph.isAccessible(x10));
|
||||||
|
|
||||||
|
Vertex<Point> x = graph.getVertex(x5);
|
||||||
|
// x5 -> x4, x5 -> x3, x5 -> x6
|
||||||
|
checkEdges(x, new Point[]{x3, x4, x6}, new Point[]{x1, x2, x7, x8, x9, x10});
|
||||||
|
// x2 -> x3, x2 -> x4
|
||||||
|
x = graph.getVertex(x2);
|
||||||
|
checkEdges(x, new Point[]{x3, x4}, new Point[]{x1, x5, x6, x7, x8, x9, x10});
|
||||||
|
// x3 -> x4, x3 -> x2, x3 -> x5, x3 -> x6
|
||||||
|
x = graph.getVertex(x3);
|
||||||
|
checkEdges(x, new Point[]{x2, x4, x5, x6}, new Point[]{x1, x7, x8, x9, x10});
|
||||||
|
// x4 -> x5, x4 -> x3, x4 -> x2, x4 -> x6
|
||||||
|
x = graph.getVertex(x4);
|
||||||
|
checkEdges(x, new Point[]{x2, x3, x5, x6}, new Point[]{x1, x7, x8, x9, x10});
|
||||||
|
// x6 -> x5, x6 -> x7, x6 -> x3, x6 -> x4
|
||||||
|
x = graph.getVertex(x6);
|
||||||
|
checkEdges(x, new Point[]{x5, x7, x3, x4}, new Point[]{x1, x2, x8, x9, x10});
|
||||||
|
// x7 -> x6, x7 -> x8
|
||||||
|
x = graph.getVertex(x7);
|
||||||
|
checkEdges(x, new Point[]{x6, x8}, new Point[]{x1, x2, x3, x4, x5, x9, x10});
|
||||||
|
// x8 <- x7
|
||||||
|
x = graph.getVertex(x8);
|
||||||
|
checkEdges(x, new Point[]{}, new Point[]{x1, x2, x3, x4, x5, x6, x7, x9, x10});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetPaths() throws Exception {
|
||||||
|
LOG.info("Start get paths test");
|
||||||
|
Graph<Point> graph = new Graph<>(x5, entrys, 5.1, 2);
|
||||||
|
// x5 <-> x4, x5 <-> x6
|
||||||
|
|
||||||
|
Collection<Path<Point>> paths = graph.getPathsTo(x4, true);
|
||||||
|
TestUtil.assertCollectionEquals(paths, Path.toPath(x5, x4));
|
||||||
|
|
||||||
|
paths = graph.getPathsTo(x6, true);
|
||||||
|
TestUtil.assertCollectionEquals(paths, Path.toPath(x5, x6));
|
||||||
|
|
||||||
|
paths = graph.getPathsTo(x7, true);
|
||||||
|
assertEquals(paths.size(), 0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetPaths2() throws Exception {
|
||||||
|
LOG.info("Start get paths test2");
|
||||||
|
Graph<Point> graph = new Graph<>(x5, entrys, 15.1, 3);
|
||||||
|
// x5 <-> x4 <-> x3 <-> x2, x5 <-> x6 <-> x7 <-> x8
|
||||||
|
// x5 <-> x3, x4 <-> x2, x3 <-> x6, x4 <-> x6
|
||||||
|
|
||||||
|
Collection<Path<Point>> paths = graph.getPathsTo(x8, true);
|
||||||
|
TestUtil.assertCollectionContainAll(paths, Path.toPath(x5, x6, x7, x8));
|
||||||
|
|
||||||
|
paths = graph.getPathsTo(x7, true);
|
||||||
|
TestUtil.assertCollectionContainAll(paths, Path.toPath(x5, x6, x7), Path.toPath(x5, x4, x6, x7), Path.toPath(x5, x3, x6, x7));
|
||||||
|
|
||||||
|
paths = graph.getPathsTo(x7, false);
|
||||||
|
TestUtil.assertCollectionContainAll(paths, Path.toPath(x5, x3, x6, x7));
|
||||||
|
|
||||||
|
paths = graph.getPathsTo(x4, true);
|
||||||
|
TestUtil.assertCollectionContainAll(paths, Path.toPath(x5, x4), Path.toPath(x5, x6, x4), Path.toPath(x5, x3, x4),
|
||||||
|
Path.toPath(x5, x6, x3, x4), Path.toPath(x5, x3, x2, x4), Path.toPath(x5, x3, x6, x4));
|
||||||
|
|
||||||
|
|
||||||
|
paths = graph.getPathsTo(x5, true);
|
||||||
|
TestUtil.assertCollectionContainAll(paths, Path.toPath(x5, x4, x5), Path.toPath(x5, x4, x6, x5), Path.toPath(x5, x4, x3, x5),
|
||||||
|
Path.toPath(x5, x6, x5), Path.toPath(x5, x6, x4, x5), Path.toPath(x5, x6, x3, x5), Path.toPath(x5, x3, x5),
|
||||||
|
Path.toPath(x5, x3, x4, x5), Path.toPath(x5, x3, x6, x5));
|
||||||
|
|
||||||
|
|
||||||
|
Path<Point> fast = graph.getFastPathTo(x8);
|
||||||
|
assertEquals(fast, Path.toPath(x5, x6, x7, x8));
|
||||||
|
|
||||||
|
fast = graph.getFastPathTo(x7);
|
||||||
|
assertEquals(fast, Path.toPath(x5, x6, x7));
|
||||||
|
|
||||||
|
fast = graph.getFastPathTo(x4);
|
||||||
|
assertEquals(fast, Path.toPath(x5, x4));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetRefillPaths() throws Exception {
|
||||||
|
LOG.info("Start get refill paths");
|
||||||
|
Graph<Point> graph = new Graph<>(x5, entrys, 10.1, 3);
|
||||||
|
// x5 <-> x4 <- refill -> x3 <- refill -> x2, x5 <-> x6
|
||||||
|
// x5 <-> x3 <- refill -> x2, x5 <-> x4 <- refill -> x6
|
||||||
|
|
||||||
|
Collection<Path<Point>> paths = graph.getPathsTo(x1, true);
|
||||||
|
assertTrue(paths.isEmpty());
|
||||||
|
|
||||||
|
paths = graph.getPathsTo(x2, true);
|
||||||
|
TestUtil.assertCollectionContainAll(paths, Path.toPath(x5, x4, x3, x2), Path.toPath(x5, x3, x2));
|
||||||
|
|
||||||
|
paths = graph.getPathsTo(x6, true);
|
||||||
|
TestUtil.assertCollectionContainAll(paths, Path.toPath(x5, x6), Path.toPath(x5, x4, x6), Path.toPath(x5, x3, x4, x6));
|
||||||
|
|
||||||
|
Path<Point> fast = graph.getFastPathTo(x2);
|
||||||
|
assertEquals(fast, Path.toPath(x5, x3, x2));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetRefillPaths2() throws Exception {
|
||||||
|
LOG.info("Start get refill paths 2 ");
|
||||||
|
Graph<Point> graph = new Graph<>(x5, entrys, 15.1, true, 4);
|
||||||
|
// x5 <-> x4 <-> x3 - refill -> x2,
|
||||||
|
// x5 <-> x6 <-> x4 <-refill -> x2
|
||||||
|
// x5 <-> x3 <- refill -> x2
|
||||||
|
// x5 <-> x4 <- refill -> x6
|
||||||
|
|
||||||
|
Collection<Path<Point>> paths = graph.getPathsTo(x1, true);
|
||||||
|
assertTrue(paths.isEmpty());
|
||||||
|
|
||||||
|
paths = graph.getPathsTo(x2, true);
|
||||||
|
TestUtil.assertCollectionContainAll(paths, Path.toPath(x5, x3, x4, x2), Path.toPath(x5, x3, x2),
|
||||||
|
Path.toPath(x5, x4, x3, x2), Path.toPath(x5, x4, x2),
|
||||||
|
Path.toPath(x5, x6, x4, x2), Path.toPath(x5, x6, x4, x3, x2));
|
||||||
|
|
||||||
|
paths = graph.getPathsTo(x6, true);
|
||||||
|
TestUtil.assertCollectionContainAll(paths, Path.toPath(x5, x6), Path.toPath(x5, x4, x6),
|
||||||
|
Path.toPath(x5, x3, x4, x6), Path.toPath(x5, x3, x6), Path.toPath(x5, x4, x3, x6));
|
||||||
|
|
||||||
|
paths = graph.getPathsTo(x7, true);
|
||||||
|
assertTrue(paths.isEmpty());
|
||||||
|
|
||||||
|
Path<Point> fast = graph.getFastPathTo(x2);
|
||||||
|
assertEquals(fast, Path.toPath(x5, x3, x2));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() throws Exception {
|
||||||
|
entrys.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
45
core/src/test/java/ru/trader/graph/Point.java
Normal file
45
core/src/test/java/ru/trader/graph/Point.java
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
package ru.trader.graph;
|
||||||
|
|
||||||
|
public class Point implements Connectable<Point> {
|
||||||
|
private int x;
|
||||||
|
private String name;
|
||||||
|
private boolean refill;
|
||||||
|
|
||||||
|
public Point(String name, int x) {
|
||||||
|
this(name, x, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Point(String name, int x, boolean refill) {
|
||||||
|
this.x = x;
|
||||||
|
this.name = name;
|
||||||
|
this.refill = refill;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
Point point = (Point) o;
|
||||||
|
return x == point.x;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getDistance(Point other) {
|
||||||
|
return Math.abs(x-other.x);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canRefill() {
|
||||||
|
return refill;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
}
|
||||||
30
core/src/test/java/ru/trader/graph/VertexTest.java
Normal file
30
core/src/test/java/ru/trader/graph/VertexTest.java
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
package ru.trader.graph;
|
||||||
|
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class VertexTest extends Assert {
|
||||||
|
private final static Logger LOG = LoggerFactory.getLogger(VertexTest.class);
|
||||||
|
|
||||||
|
private final static Point x1 = new Point("x1",1);
|
||||||
|
private final static Point x2 = new Point("x2",4);
|
||||||
|
private final static Point x3 = new Point("x3",-2);
|
||||||
|
private final static Point x4 = new Point("x4",5);
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testContains() throws Exception {
|
||||||
|
LOG.info("Start vertex contains test");
|
||||||
|
|
||||||
|
Vertex<Point> vertex = new Vertex<>(x1);
|
||||||
|
vertex.addEdge(new Edge<>(vertex, new Vertex<>(x2)));
|
||||||
|
vertex.addEdge(new Edge<>(vertex, x3));
|
||||||
|
|
||||||
|
assertFalse("Vertex must contains entry",vertex.isConnected(x1));
|
||||||
|
assertTrue("Vertex must contains entry",vertex.isConnected(new Vertex<>(x3)));
|
||||||
|
assertTrue("Vertex must contains entry",vertex.isConnected(x2));
|
||||||
|
assertFalse("Vertex not must contains entry", vertex.isConnected(new Vertex<>(x4)));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,8 @@ package ru.trader.store;
|
|||||||
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
import org.xml.sax.SAXException;
|
import org.xml.sax.SAXException;
|
||||||
import ru.trader.core.Market;
|
import ru.trader.core.Market;
|
||||||
|
|
||||||
@@ -10,9 +12,11 @@ import java.io.IOException;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
public class LoadTest extends Assert {
|
public class LoadTest extends Assert {
|
||||||
|
private final static Logger LOG = LoggerFactory.getLogger(LoadTest.class);
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testLoad(){
|
public void testLoad(){
|
||||||
|
LOG.info("Start world load test");
|
||||||
InputStream is = getClass().getResourceAsStream("/test.xml");
|
InputStream is = getClass().getResourceAsStream("/test.xml");
|
||||||
Market world;
|
Market world;
|
||||||
try {
|
try {
|
||||||
|
|||||||
6
core/src/test/resources/log4j.properties
Normal file
6
core/src/test/resources/log4j.properties
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
log4j.rootLogger = INFO, stdout
|
||||||
|
|
||||||
|
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
|
||||||
|
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
|
||||||
|
log4j.appender.stdout.layout.ConversionPattern=%p: %d{dd.MM.yyyy HH:mm:ss} (%F:%L) - %m%n
|
||||||
|
|
||||||
Reference in New Issue
Block a user