Archived
0

add time and profit to route entry

This commit is contained in:
iMoHax
2015-08-10 16:18:45 +03:00
parent 096af8d868
commit f04c050843
9 changed files with 135 additions and 50 deletions

View File

@@ -13,8 +13,8 @@ public class Route implements Comparable<Route> {
private double profit = 0; private double profit = 0;
private double balance = 0; private double balance = 0;
private double distance = 0; private double distance = 0;
private double score = 0;
private double fuel = 0; private double fuel = 0;
private double time = 0;
private int lands = 0; private int lands = 0;
private int refills = 0; private int refills = 0;
@@ -64,6 +64,18 @@ public class Route implements Comparable<Route> {
return refills; return refills;
} }
public double getTime() {
return time;
}
public double getFuel() {
return fuel;
}
public double getScore() {
return profit / time;
}
public void add(RouteEntry entry){ public void add(RouteEntry entry){
LOG.trace("Add entry {} to route {}", entry, this); LOG.trace("Add entry {} to route {}", entry, this);
entries.add(entry); entries.add(entry);
@@ -120,7 +132,7 @@ public class Route implements Comparable<Route> {
} }
void updateStats(){ void updateStats(){
LOG.trace("Update stats, old: profit={}, distance={}, lands={}, fuel={}, refills={}, score={}", profit, distance, lands, fuel, refills, score); LOG.trace("Update stats, old: profit={}, distance={}, lands={}, fuel={}, refills={}, time={}", profit, distance, lands, fuel, refills, time);
profit = 0; distance = 0; lands = 0; fuel = 0; refills = 0; profit = 0; distance = 0; lands = 0; fuel = 0; refills = 0;
if (entries.isEmpty()) return; if (entries.isEmpty()) return;
RouteEntry entry = entries.get(0); RouteEntry entry = entries.get(0);
@@ -128,7 +140,7 @@ public class Route implements Comparable<Route> {
RouteEntry next = entries.get(i); RouteEntry next = entries.get(i);
distance += entry.getVendor().getDistance(next.getVendor()); distance += entry.getVendor().getDistance(next.getVendor());
profit += entry.getProfit(); profit += entry.getProfit();
score += entry.getScore(); time += entry.getFullTime();
fuel += entry.getFuel(); fuel += entry.getFuel();
if (entry.isLand()){ if (entry.isLand()){
lands++; lands++;
@@ -138,12 +150,12 @@ public class Route implements Comparable<Route> {
} }
entry = next; entry = next;
} }
LOG.trace("new stats profit={}, distance={}, lands={}, fuel={}, score={}", profit, distance, lands, fuel, score); LOG.trace("new stats profit={}, distance={}, lands={}, fuel={}, time={}", profit, distance, lands, fuel, time);
} }
@Override @Override
public int compareTo(Route o) { public int compareTo(Route o) {
return Double.compare(score, o.score); return Double.compare(getScore(), o.getScore());
} }
@Override @Override
@@ -151,7 +163,7 @@ public class Route implements Comparable<Route> {
if (this == o) return true; if (this == o) return true;
if (!(o instanceof Route)) return false; if (!(o instanceof Route)) return false;
Route route = (Route) o; Route route = (Route) o;
return Double.compare(route.profit, profit) == 0 && entries.equals(route.entries); return (Double.compare(route.profit, profit) == 0 || Math.abs(profit - route.profit) < 0.1)&& entries.equals(route.entries);
} }
@Override @Override
@@ -166,7 +178,8 @@ public class Route implements Comparable<Route> {
", profit=" + profit + ", profit=" + profit +
", balance=" + balance + ", balance=" + balance +
", distance=" + distance + ", distance=" + distance +
", score=" + score + ", time=" + time +
", score=" + getScore() +
", fuel=" + fuel + ", fuel=" + fuel +
", lands=" + lands + ", lands=" + lands +
'}'; '}';

View File

@@ -13,14 +13,16 @@ public class RouteEntry {
private final List<Order> orders; private final List<Order> orders;
private boolean land; private boolean land;
private double refill; private double refill;
private double score; private double profit;
private double time;
private double fulltime;
public RouteEntry(Vendor vendor, double refill, double fuel, double score) { public RouteEntry(Vendor vendor, double refill, double fuel, double profit) {
orders = new ArrayList<>(); orders = new ArrayList<>();
this.vendor = vendor; this.vendor = vendor;
this.refill = refill; this.refill = refill;
this.fuel = fuel; this.fuel = fuel;
this.score = score; this.profit = profit;
} }
public Vendor getVendor() { public Vendor getVendor() {
@@ -47,12 +49,28 @@ public class RouteEntry {
return fuel; return fuel;
} }
public double getScore() { public double getProfit() {
return score; return profit;
} }
void setScore(double score) { void setProfit(double profit) {
this.score = score; this.profit = profit;
}
public double getTime() {
return time;
}
void setTime(double time) {
this.time = time;
}
public double getFullTime() {
return fulltime;
}
void setFullTime(double fullTime) {
this.fulltime = fullTime;
} }
void add(Order order){ void add(Order order){
@@ -71,7 +89,7 @@ public class RouteEntry {
orders.clear(); orders.clear();
} }
public double getProfit(){ public double getProfitByOrders(){
return orders.stream().mapToDouble(Order::getProfit).sum(); return orders.stream().mapToDouble(Order::getProfit).sum();
} }
@@ -97,6 +115,7 @@ public class RouteEntry {
if (refill != that.refill) return false; if (refill != that.refill) return false;
if (Double.compare(that.fuel, fuel) != 0) return false; if (Double.compare(that.fuel, fuel) != 0) return false;
if (orders.size() != that.orders.size()) return false; if (orders.size() != that.orders.size()) return false;
if (time != that.time) return false;
return vendor.equals(that.vendor); return vendor.equals(that.vendor);
} }
@@ -109,7 +128,7 @@ public class RouteEntry {
result = 31 * result + (int) (temp ^ (temp >>> 32)); result = 31 * result + (int) (temp ^ (temp >>> 32));
result = 31 * result + (land ? 1 : 0); result = 31 * result + (land ? 1 : 0);
result = 31 * result + (isRefill() ? 1 : 0); result = 31 * result + (isRefill() ? 1 : 0);
temp = Double.doubleToLongBits(score); temp = Double.doubleToLongBits(profit);
result = 31 * result + (int) (temp ^ (temp >>> 32)); result = 31 * result + (int) (temp ^ (temp >>> 32));
return result; return result;
} }

View File

@@ -176,8 +176,15 @@ public class RouteFiller {
if (best != TRANSIT) if (best != TRANSIT)
entry.addAll(best.bestOrders); entry.addAll(best.bestOrders);
} }
int jumps = i==0 || entries.get(i-1).getVendor().getPlace().equals(entry.getVendor().getPlace())? 0 : 1; RouteEntry prev = i != 0 ? entries.get(i-1) : null;
entry.setScore(i==0 ? 0 : scorer.getScore(entry, jumps)); if (prev != null){
prev.setProfit(scorer.getProfit(prev.getProfitByOrders(), prev.getFuel()));
prev.setTime(scorer.getTime(entry, prev));
prev.setFullTime(prev.getTime());
} else {
entry.setProfit(0);
entry.setTime(0);
}
} }
} }

View File

@@ -24,6 +24,10 @@ public class RouteSearcher {
this.callback = callback; this.callback = callback;
} }
public Scorer getScorer() {
return scorer;
}
public List<Edge<Place>> getPath(Place from, Place to, Collection<Place> places){ public List<Edge<Place>> getPath(Place from, Place to, Collection<Place> places){
List<List<Edge<Place>>> res = search(from, to, places, 1, null); List<List<Edge<Place>>> res = search(from, to, places, 1, null);
return res.isEmpty() ? null : res.get(0); return res.isEmpty() ? null : res.get(0);
@@ -103,8 +107,7 @@ public class RouteSearcher {
private List<Route> routes = new ArrayList<>(); private List<Route> routes = new ArrayList<>();
public void add(List<Edge<Vendor>> edges){ public void add(List<Edge<Vendor>> edges){
Route route = toRoute(edges); Route route = toRoute(edges, scorer);
route.setBalance(scorer.getProfile().getBalance());
routes.add(route); routes.add(route);
} }
@@ -113,10 +116,11 @@ public class RouteSearcher {
} }
} }
public static Route toRoute(List<Edge<Vendor>> edges){ public static Route toRoute(List<Edge<Vendor>> edges, final Scorer scorer){
List<RouteEntry> entries = new ArrayList<>(edges.size()+1); List<RouteEntry> entries = new ArrayList<>(edges.size()+1);
Vendor buyer = null; Vendor buyer = null;
VendorsGraph.VendorsEdge vEdge = null; VendorsGraph.VendorsEdge vEdge = null;
RouteEntry prev = null;
for (Edge<Vendor> e : edges) { for (Edge<Vendor> e : edges) {
vEdge = (VendorsGraph.VendorsEdge) e; vEdge = (VendorsGraph.VendorsEdge) e;
List<ConnectibleEdge<Vendor>> transitEdges = vEdge.getPath().getEntries(); List<ConnectibleEdge<Vendor>> transitEdges = vEdge.getPath().getEntries();
@@ -129,45 +133,67 @@ public class RouteSearcher {
buyer = null; buyer = null;
} }
if (k == 0) { if (k == 0) {
entry.setScore(vEdge.getWeight()); entry.setProfit(scorer.getProfit(vEdge.getProfit(), vEdge.getFuelCost()));
entry.setFullTime(vEdge.getTime());
List<Order> orders = vEdge.getOrders(); List<Order> orders = vEdge.getOrders();
if (!orders.isEmpty()) { if (!orders.isEmpty()) {
buyer = orders.get(0).getBuyer(); buyer = orders.get(0).getBuyer();
entry.addAll(orders); entry.addAll(orders);
} }
} }
if (prev != null){
prev.setTime(scorer.getTime(entry, prev));
}
entries.add(entry); entries.add(entry);
prev = entry;
} }
} }
if (vEdge != null) { if (vEdge != null) {
RouteEntry entry = new RouteEntry(vEdge.getTarget().getEntry(), 0, 0, 0); RouteEntry entry = new RouteEntry(vEdge.getTarget().getEntry(), 0, 0, 0);
if (buyer != null) entry.setLand(true); if (buyer != null) entry.setLand(true);
if (prev != null){
prev.setTime(scorer.getTime(entry, prev));
}
entries.add(entry); entries.add(entry);
} }
return new Route(entries); Route route = new Route(entries);
route.setBalance(scorer.getProfile().getBalance());
return route;
} }
public static Route toRoute(Order order, List<Edge<Place>> edges){ public static Route toRoute(Order order, List<Edge<Place>> edges, final Scorer scorer){
Route route = toRoute(order.getSeller(), order.getBuyer(), edges); Route route = toRoute(order.getSeller(), order.getBuyer(), edges, scorer);
if (route.isEmpty()) return route; if (route.isEmpty()) return route;
route.get(0).add(order); route.get(0).add(order);
route.updateStats(); route.updateStats();
return route; return route;
} }
public static Route toRoute(Vendor from, Vendor to, List<Edge<Place>> edges){ public static Route toRoute(Vendor from, Vendor to, List<Edge<Place>> edges, final Scorer scorer){
List<RouteEntry> entries = new ArrayList<>(edges.size()+1); List<RouteEntry> entries = new ArrayList<>(edges.size()+1);
RouteEntry prev = null;
for (int i = 0; i < edges.size(); i++) { for (int i = 0; i < edges.size(); i++) {
ConnectibleEdge<Place> edge = (ConnectibleEdge<Place>) edges.get(i); ConnectibleEdge<Place> edge = (ConnectibleEdge<Place>) edges.get(i);
Vendor vendor = i == 0 ? from : edge.getSource().getEntry().asTransit(); Vendor vendor = i == 0 ? from : edge.getSource().getEntry().asTransit();
RouteEntry entry = new RouteEntry(vendor, edge.getRefill(), edge.getFuelCost(), 0); RouteEntry entry = new RouteEntry(vendor, edge.getRefill(), edge.getFuelCost(), 0);
if (prev != null){
prev.setTime(scorer.getTime(entry, prev));
prev.setFullTime(prev.getTime());
}
entries.add(entry); entries.add(entry);
if (i == edges.size()-1){ if (i == edges.size()-1){
entry = new RouteEntry(to, 0, 0, 0); entry = new RouteEntry(to, 0, 0, 0);
entry.setLand(true); entry.setLand(true);
if (prev != null){
prev.setTime(scorer.getTime(entry, prev));
prev.setFullTime(prev.getTime());
}
entries.add(entry); entries.add(entry);
} }
prev = entry;
} }
return new Route(entries); Route route = new Route(entries);
route.setBalance(scorer.getProfile().getBalance());
return route;
} }
} }

View File

@@ -95,15 +95,6 @@ public class Scorer {
return avgDistance; return avgDistance;
} }
public double getScore(RouteEntry entry, int jumps) {
int lands = entry.isLand() ? 1 : 0;
return getScore(entry.getVendor(), entry.getProfit(), jumps, lands, entry.getFuel());
}
public double getScore(Vendor vendor, double profit, int jumps, int lands, double fuel) {
return getScore(vendor.getDistance(), profit, jumps, lands, fuel);
}
private double getTime(double distance){ private double getTime(double distance){
double a = 6000; double a = 6000;
double b = 673; double b = 673;
@@ -111,26 +102,50 @@ public class Scorer {
return Math.log(distance + a)*b*profile.getDistanceTime() - c; return Math.log(distance + a)*b*profile.getDistanceTime() - c;
} }
public double getProfitByTonne(double profit, double fuel){
return getProfit(profit, fuel) / profile.getShip().getCargo();
}
public double getProfit(double profit, double fuel){ public double getProfit(double profit, double fuel){
profit -= profile.getFuelPrice() * fuel; profit -= profile.getFuelPrice() * fuel;
profit = profit / profile.getShip().getCargo();
return profit; return profit;
} }
public double getTime(RouteEntry entry, RouteEntry prev) {
if (prev == null) return 0;
int lands = entry.isLand() ? 1 : 0;
int jumps = prev.getVendor().getPlace().equals(entry.getVendor().getPlace()) ? 0 : 1;
double time = getTime(entry.getVendor().getDistance(), jumps, lands);
if (!prev.isLand()){
time = time - profile.getTakeoffTime() + profile.getRechargeTime();
}
return time;
}
public double getTime(double distance, int jumps, int lands){ public double getTime(double distance, int jumps, int lands){
double time = profile.getTakeoffTime(); double time = profile.getTakeoffTime();
if (jumps > 0){ if (jumps > 0){
time += profile.getJumpTime() + (jumps-1) * (profile.getRechargeTime() + profile.getJumpTime()); time += profile.getJumpTime() + (jumps-1) * (profile.getRechargeTime() + profile.getJumpTime());
} }
if (profile.getLandingTime() > 0){ if (profile.getLandingTime() > 0 & lands > 0){
time += (lands-1)*(getTime(avgDistance) + profile.getLandingTime() + profile.getTakeoffTime()) + getTime(distance) + profile.getLandingTime(); time += (lands-1)*(getTime(avgDistance) + profile.getLandingTime() + profile.getTakeoffTime()) + getTime(distance) + profile.getLandingTime();
} }
return time; return time;
} }
public double getScore(RouteEntry entry, RouteEntry prev) {
int lands = prev.isLand() ? 1 : 0;
int jumps = prev.getVendor().getPlace().equals(entry.getVendor().getPlace())? 0 : 1;
return getScore(prev.getVendor(), prev.getProfit(), jumps, lands, prev.getFuel());
}
public double getScore(Vendor vendor, double profit, int jumps, int lands, double fuel) {
return getScore(vendor.getDistance(), profit, jumps, lands, fuel);
}
public double getScore(double distance, double profit, int jumps, int lands, double fuel){ public double getScore(double distance, double profit, int jumps, int lands, double fuel){
LOG.trace("Compute score distance={}, profit={}, jumps={}, lands={}, fuel={}", distance, profit, jumps, lands, fuel); LOG.trace("Compute score distance={}, profit={}, jumps={}, lands={}, fuel={}", distance, profit, jumps, lands, fuel);
double score = getProfit(profit, fuel)/getTime(distance, jumps, lands); double score = getProfitByTonne(profit, fuel)/getTime(distance, jumps, lands);
LOG.trace("score={}", score); LOG.trace("score={}", score);
return score; return score;
} }

View File

@@ -383,10 +383,19 @@ public class VendorsGraph extends ConnectibleGraph<Vendor> {
return path.getRemain(); return path.getRemain();
} }
@Override
public boolean isRefill() { public boolean isRefill() {
return path.isRefill(); return path.isRefill();
} }
@Override
public double getFuelCost() {
if (path != null){
return path.getFuelCost();
}
return super.getFuelCost();
}
public TransitPath getPath() { public TransitPath getPath() {
return path; return path;
} }
@@ -415,11 +424,7 @@ public class VendorsGraph extends ConnectibleGraph<Vendor> {
} }
protected double computeProfit(){ protected double computeProfit(){
double fuel = fuelCost; return scorer.getProfitByTonne(getProfit(), getFuelCost());
if (path != null){
fuel = path.getFuelCost();
}
return scorer.getProfit(getProfit(), fuel);
} }
protected double computeTime(){ protected double computeTime(){

View File

@@ -176,11 +176,11 @@ public class MarketAnalyzer {
} }
public Route getPath(Vendor from, Vendor to){ public Route getPath(Vendor from, Vendor to){
return RouteSearcher.toRoute(from, to, searcher.getPath(from.getPlace(), to.getPlace(), getPlaces())); return RouteSearcher.toRoute(from, to, searcher.getPath(from.getPlace(), to.getPlace(), getPlaces()), searcher.getScorer());
} }
public Route getPath(Order order){ public Route getPath(Order order){
return RouteSearcher.toRoute(order, searcher.getPath(order.getSeller().getPlace(), order.getBuyer().getPlace(), getPlaces())); return RouteSearcher.toRoute(order, searcher.getPath(order.getSeller().getPlace(), order.getBuyer().getPlace(), getPlaces()), searcher.getScorer());
} }
public Collection<Route> getTopRoutes(int limit){ public Collection<Route> getTopRoutes(int limit){

View File

@@ -74,7 +74,7 @@ public class RouteSearcherTest extends Assert{
RouteFiller filler = new RouteFiller(scorer); RouteFiller filler = new RouteFiller(scorer);
filler.fill(route); filler.fill(route);
assertEquals(981200, route.getProfit(), 0); assertEquals(978883.1, route.getProfit(), 0.1);
assertEquals(2, route.getLands()); assertEquals(2, route.getLands());
assertEquals(72.42, route.getDistance(), 0.01); assertEquals(72.42, route.getDistance(), 0.01);
@@ -102,7 +102,7 @@ public class RouteSearcherTest extends Assert{
filler = new RouteFiller(scorer); filler = new RouteFiller(scorer);
filler.fill(route); filler.fill(route);
assertEquals(1971200, route.getProfit(), 0); assertEquals(1967873.6, route.getProfit(), 0.1);
assertEquals(4, route.getLands()); assertEquals(4, route.getLands());
assertEquals(109.51, route.getDistance(), 0.01); assertEquals(109.51, route.getDistance(), 0.01);

View File

@@ -45,7 +45,7 @@ public class MarketAnalyzerTest2 extends Assert {
assertTrue(path.isPresent()); assertTrue(path.isPresent());
Route actual = path.get(); Route actual = path.get();
assertEquals(expect, actual); assertEquals(expect, actual);
assertEquals(981200, actual.getProfit(), 0.00001); assertEquals(978883.1, actual.getProfit(), 0.1);
assertEquals(72.42, actual.getDistance(), 0.01); assertEquals(72.42, actual.getDistance(), 0.01);
assertEquals(2, actual.getLands()); assertEquals(2, actual.getLands());
} }
@@ -78,7 +78,7 @@ public class MarketAnalyzerTest2 extends Assert {
assertTrue(path.isPresent()); assertTrue(path.isPresent());
Route actual = path.get(); Route actual = path.get();
assertEquals(199056, actual.getProfit(), 0.00001); assertEquals(198127.6, actual.getProfit(), 0.1);
assertEquals(28.72, actual.getDistance(), 0.01); assertEquals(28.72, actual.getDistance(), 0.01);
assertEquals(2, actual.getLands()); assertEquals(2, actual.getLands());