Archived
0

Increase search speed, add minimum vendor rating parameter for skip low profitable vendors

This commit is contained in:
iMoHax
2016-10-14 15:57:14 +03:00
parent 77c12f6194
commit 374e1d6c62
9 changed files with 197 additions and 105 deletions

View File

@@ -36,6 +36,8 @@ public class SettingsController {
@FXML @FXML
private NumberField routesCount; private NumberField routesCount;
@FXML @FXML
private NumberField minVendorRating;
@FXML
private NumberField fuelPrice; private NumberField fuelPrice;
@FXML @FXML
private ComboBox<Profile.PATH_PRIORITY> pathPriority; private ComboBox<Profile.PATH_PRIORITY> pathPriority;
@@ -93,6 +95,7 @@ public class SettingsController {
jumps.setValue(profile.getJumps()); jumps.setValue(profile.getJumps());
lands.setValue(profile.getLands()); lands.setValue(profile.getLands());
routesCount.setValue(profile.getRoutesCount()); routesCount.setValue(profile.getRoutesCount());
minVendorRating.setValue(profile.getMinVendorRating());
fuelPrice.setValue(profile.getFuelPrice()); fuelPrice.setValue(profile.getFuelPrice());
pathPriority.setValue(profile.getPathPriority()); pathPriority.setValue(profile.getPathPriority());
jumpTime.setValue(profile.getJumpTime()); jumpTime.setValue(profile.getJumpTime());
@@ -134,6 +137,7 @@ public class SettingsController {
profile.setJumps(jumps.getValue().intValue()); profile.setJumps(jumps.getValue().intValue());
profile.setLands(lands.getValue().intValue()); profile.setLands(lands.getValue().intValue());
profile.setRoutesCount(routesCount.getValue().intValue()); profile.setRoutesCount(routesCount.getValue().intValue());
profile.setMinVendorRating(minVendorRating.getValue().doubleValue());
profile.setFuelPrice(fuelPrice.getValue().intValue()); profile.setFuelPrice(fuelPrice.getValue().intValue());
profile.setPathPriority(pathPriority.getValue()); profile.setPathPriority(pathPriority.getValue());
profile.setJumpTime(jumpTime.getValue().intValue()); profile.setJumpTime(jumpTime.getValue().intValue());

View File

@@ -184,13 +184,14 @@ settings.emdn.on=Active
settings.emdn.sub=Server SUB: settings.emdn.sub=Server SUB:
settings.emdn.updateOnly=Update price only: settings.emdn.updateOnly=Update price only:
settings.emdn.auto=Auto update (sec.): settings.emdn.auto=Auto update (sec.):
settings.edce.on=Active
settings.edce.interval=Update interval, sec.
settings.performance=Performance settings.performance=Performance
settings.performance.segmentSize=Segment size (0 - auto): settings.performance.segmentSize=Segment size (0 - auto):
settings.performance.limit=Routes count: settings.performance.limit=Routes count:
settings.edce.on=Active
settings.edce.interval=Update interval, sec.
settings.performance.jumps=Jumps: settings.performance.jumps=Jumps:
settings.performance.landings=Landings: settings.performance.landings=Landings:
settings.performance.minVendorRating=Minimal station rating (0-10):
settings.search=Search options settings.search=Search options
settings.search.fuelPrice=1t fuel price: settings.search.fuelPrice=1t fuel price:
settings.search.pathType=Path priority: settings.search.pathType=Path priority:

View File

@@ -183,13 +183,14 @@ settings.emdn.on=\u0412\u043A\u043B\u044E\u0447\u0438\u0442\u044C
settings.emdn.sub=\u0421\u0435\u0440\u0432\u0435\u0440 SUB: settings.emdn.sub=\u0421\u0435\u0440\u0432\u0435\u0440 SUB:
settings.emdn.updateOnly=\u0422\u043E\u043B\u044C\u043A\u043E \u043E\u0431\u043D\u043E\u0432\u043B\u044F\u0442\u044C \u0446\u0435\u043D\u044B: settings.emdn.updateOnly=\u0422\u043E\u043B\u044C\u043A\u043E \u043E\u0431\u043D\u043E\u0432\u043B\u044F\u0442\u044C \u0446\u0435\u043D\u044B:
settings.emdn.auto=\u041E\u0431\u043D\u043E\u0432\u043B\u044F\u0442\u044C \u0430\u0442\u043E\u043C\u0430\u0442\u0438\u0447\u0435\u0441\u043A\u0438 \u0447\u0435\u0440\u0435\u0437 (\u0441\u0435\u043A.): settings.emdn.auto=\u041E\u0431\u043D\u043E\u0432\u043B\u044F\u0442\u044C \u0430\u0442\u043E\u043C\u0430\u0442\u0438\u0447\u0435\u0441\u043A\u0438 \u0447\u0435\u0440\u0435\u0437 (\u0441\u0435\u043A.):
settings.edce.on=\u0412\u043A\u043B\u044E\u0447\u0438\u0442\u044C
settings.edce.interval=\u0418\u043D\u0442\u0435\u0440\u0432\u0430\u043B, \u0441\u0435\u043A.
settings.performance=\u041F\u0440\u043E\u0438\u0437\u0432\u043E\u0434\u0438\u0442\u0435\u043B\u044C\u043D\u043E\u0441\u0442\u044C settings.performance=\u041F\u0440\u043E\u0438\u0437\u0432\u043E\u0434\u0438\u0442\u0435\u043B\u044C\u043D\u043E\u0441\u0442\u044C
settings.performance.segmentSize=\u041C\u0430\u0440\u0448\u0440\u0443\u0442\u043E\u0432 \u0432 \u0441\u0435\u0433\u043C\u0435\u043D\u0442\u0435 (0 - \u0430\u0432\u0442\u043E): settings.performance.segmentSize=\u041C\u0430\u0440\u0448\u0440\u0443\u0442\u043E\u0432 \u0432 \u0441\u0435\u0433\u043C\u0435\u043D\u0442\u0435 (0 - \u0430\u0432\u0442\u043E):
settings.performance.limit=\u041A\u043E\u043B-\u0432\u043E \u043C\u0430\u0440\u0448\u0440\u0443\u0442\u043E\u0432 \u043D\u0430 \u0432\u044B\u0432\u043E\u0434: settings.performance.limit=\u041A\u043E\u043B-\u0432\u043E \u043C\u0430\u0440\u0448\u0440\u0443\u0442\u043E\u0432 \u043D\u0430 \u0432\u044B\u0432\u043E\u0434:
settings.edce.on=\u0412\u043A\u043B\u044E\u0447\u0438\u0442\u044C
settings.edce.interval=\u0418\u043D\u0442\u0435\u0440\u0432\u0430\u043B, \u0441\u0435\u043A.
settings.performance.jumps=\u041F\u0440\u044B\u0436\u043A\u043E\u0432: settings.performance.jumps=\u041F\u0440\u044B\u0436\u043A\u043E\u0432:
settings.performance.landings=\u041F\u043E\u0441\u0430\u0434\u043E\u043A: settings.performance.landings=\u041F\u043E\u0441\u0430\u0434\u043E\u043A:
settings.performance.minVendorRating=\u041C\u0438\u043D\u0438\u043C\u0430\u043B\u044C\u043D\u044B\u0439 \u0440\u0435\u0439\u0442\u0438\u043D\u0433 \u0441\u0442\u0430\u043D\u0446\u0438\u0438 (0-10):
settings.search=\u041F\u0430\u0440\u0430\u043C\u0435\u0442\u0440\u044B \u043F\u043E\u0438\u0441\u043A\u0430 settings.search=\u041F\u0430\u0440\u0430\u043C\u0435\u0442\u0440\u044B \u043F\u043E\u0438\u0441\u043A\u0430
settings.search.fuelPrice=\u0421\u0442\u043E\u0438\u043C\u043E\u0441\u0442\u044C 1\u0442 \u0442\u043E\u043F\u043B\u0438\u0432\u0430: settings.search.fuelPrice=\u0421\u0442\u043E\u0438\u043C\u043E\u0441\u0442\u044C 1\u0442 \u0442\u043E\u043F\u043B\u0438\u0432\u0430:
settings.search.pathType=\u0422\u0438\u043F \u043C\u0430\u0440\u0448\u0440\u0443\u0442\u043E\u0432: settings.search.pathType=\u0422\u0438\u043F \u043C\u0430\u0440\u0448\u0440\u0443\u0442\u043E\u0432:

View File

@@ -2,8 +2,9 @@
<?import javafx.scene.layout.*?> <?import javafx.scene.layout.*?>
<?import ru.trader.view.support.*?> <?import ru.trader.view.support.*?>
<?import org.controlsfx.glyphfont.Glyph?> <?import org.controlsfx.glyphfont.Glyph?>
<GridPane xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="ru.trader.controllers.SettingsController" <ScrollPane xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="ru.trader.controllers.SettingsController"
styleClass="dialog" vgap="4" hgap="8"> styleClass="dialog">
<GridPane vgap="4" hgap="8">
<columnConstraints> <columnConstraints>
<ColumnConstraints /> <ColumnConstraints />
<ColumnConstraints minWidth="260" maxWidth="260"/> <ColumnConstraints minWidth="260" maxWidth="260"/>
@@ -26,38 +27,40 @@
<NumberField fx:id="lands" maxWidth="100" GridPane.columnIndex="1" GridPane.rowIndex="5" /> <NumberField fx:id="lands" maxWidth="100" GridPane.columnIndex="1" GridPane.rowIndex="5" />
<Label text="%settings.performance.limit" GridPane.rowIndex="6" /> <Label text="%settings.performance.limit" GridPane.rowIndex="6" />
<NumberField fx:id="routesCount" maxWidth="100" GridPane.columnIndex="1" GridPane.rowIndex="6" /> <NumberField fx:id="routesCount" maxWidth="100" GridPane.columnIndex="1" GridPane.rowIndex="6" />
<Label text="%settings.search" styleClass="settings-group" GridPane.halignment="CENTER" GridPane.columnSpan="2" GridPane.rowIndex="7"/> <Label text="%settings.performance.minVendorRating" GridPane.rowIndex="7" />
<Label text="%settings.search.fuelPrice" GridPane.rowIndex="8" /> <NumberField fx:id="minVendorRating" maxWidth="100" GridPane.columnIndex="1" GridPane.rowIndex="7" />
<NumberField fx:id="fuelPrice" maxWidth="100" GridPane.columnIndex="1" GridPane.rowIndex="8" /> <Label text="%settings.search" styleClass="settings-group" GridPane.halignment="CENTER" GridPane.columnSpan="2" GridPane.rowIndex="8"/>
<Label text="%settings.search.pathType" GridPane.rowIndex="9" /> <Label text="%settings.search.fuelPrice" GridPane.rowIndex="9" />
<ComboBox fx:id="pathPriority" maxWidth="100" GridPane.columnIndex="1" GridPane.rowIndex="9" /> <NumberField fx:id="fuelPrice" maxWidth="100" GridPane.columnIndex="1" GridPane.rowIndex="9" />
<Label text="%settings.search.times.jump" GridPane.rowIndex="10" /> <Label text="%settings.search.pathType" GridPane.rowIndex="10" />
<NumberField fx:id="jumpTime" maxWidth="100" GridPane.columnIndex="1" GridPane.rowIndex="10" /> <ComboBox fx:id="pathPriority" maxWidth="100" GridPane.columnIndex="1" GridPane.rowIndex="10" />
<Label text="%settings.search.times.landing" GridPane.rowIndex="11" /> <Label text="%settings.search.times.jump" GridPane.rowIndex="11" />
<NumberField fx:id="landingTime" maxWidth="100" GridPane.columnIndex="1" GridPane.rowIndex="11" /> <NumberField fx:id="jumpTime" maxWidth="100" GridPane.columnIndex="1" GridPane.rowIndex="11" />
<Label text="%settings.search.times.orbital" GridPane.rowIndex="12" /> <Label text="%settings.search.times.landing" GridPane.rowIndex="12" />
<NumberField fx:id="orbitalTime" maxWidth="100" GridPane.columnIndex="1" GridPane.rowIndex="12" /> <NumberField fx:id="landingTime" maxWidth="100" GridPane.columnIndex="1" GridPane.rowIndex="12" />
<Label text="%settings.search.times.takeoff" GridPane.rowIndex="13" /> <Label text="%settings.search.times.orbital" GridPane.rowIndex="13" />
<NumberField fx:id="takeoffTime" maxWidth="100" GridPane.columnIndex="1" GridPane.rowIndex="13" /> <NumberField fx:id="orbitalTime" maxWidth="100" GridPane.columnIndex="1" GridPane.rowIndex="13" />
<Label text="%settings.search.times.recharge" GridPane.rowIndex="14" /> <Label text="%settings.search.times.takeoff" GridPane.rowIndex="14" />
<NumberField fx:id="rechargeTime" maxWidth="100" GridPane.columnIndex="1" GridPane.rowIndex="14" /> <NumberField fx:id="takeoffTime" maxWidth="100" GridPane.columnIndex="1" GridPane.rowIndex="14" />
<Label text="%settings.hotkeys" styleClass="settings-group" GridPane.halignment="CENTER" GridPane.columnSpan="2" GridPane.rowIndex="15"/> <Label text="%settings.search.times.recharge" GridPane.rowIndex="15" />
<Label text="%settings.hotkeys.complete" GridPane.rowIndex="16" /> <NumberField fx:id="rechargeTime" maxWidth="100" GridPane.columnIndex="1" GridPane.rowIndex="15" />
<TextField fx:id="completeKeyText" maxWidth="100" GridPane.columnIndex="1" GridPane.rowIndex="16" /> <Label text="%settings.hotkeys" styleClass="settings-group" GridPane.halignment="CENTER" GridPane.columnSpan="2" GridPane.rowIndex="16"/>
<Label text="ED Log Watcher" styleClass="settings-group" GridPane.halignment="CENTER" GridPane.columnSpan="2" GridPane.rowIndex="17"/> <Label text="%settings.hotkeys.complete" GridPane.rowIndex="17" />
<Label text="%settings.edlog.on" GridPane.rowIndex="18"/> <TextField fx:id="completeKeyText" maxWidth="100" GridPane.columnIndex="1" GridPane.rowIndex="17" />
<CheckBox fx:id="edLogActive" GridPane.columnIndex="1" GridPane.rowIndex="18"/> <Label text="ED Log Watcher" styleClass="settings-group" GridPane.halignment="CENTER" GridPane.columnSpan="2" GridPane.rowIndex="18"/>
<Label text="%settings.edlog.dir" GridPane.rowIndex="19" /> <Label text="%settings.edlog.on" GridPane.rowIndex="19"/>
<HBox maxWidth="260" GridPane.columnIndex="1" GridPane.rowIndex="19"> <CheckBox fx:id="edLogActive" GridPane.columnIndex="1" GridPane.rowIndex="19"/>
<Label text="%settings.edlog.dir" GridPane.rowIndex="20" />
<HBox maxWidth="260" GridPane.columnIndex="1" GridPane.rowIndex="20">
<TextField fx:id="edLogDir" /> <TextField fx:id="edLogDir" />
<Button minWidth="30" minHeight="25" onAction="#selectLogDir"><graphic><Glyph text="FontAwesome|FOLDER_OPEN"/></graphic></Button> <Button minWidth="30" minHeight="25" onAction="#selectLogDir"><graphic><Glyph text="FontAwesome|FOLDER_OPEN"/></graphic></Button>
</HBox> </HBox>
<Label text="%settings.emdn" styleClass="settings-group" GridPane.halignment="CENTER" GridPane.columnSpan="2" GridPane.rowIndex="20"/> <Label text="%settings.emdn" styleClass="settings-group" GridPane.halignment="CENTER" GridPane.columnSpan="2" GridPane.rowIndex="21"/>
<Label text="%settings.emdn.on" GridPane.rowIndex="21"/> <Label text="%settings.emdn.on" GridPane.rowIndex="22"/>
<CheckBox fx:id="emdnOn" GridPane.columnIndex="1" GridPane.rowIndex="21"/> <CheckBox fx:id="emdnOn" GridPane.columnIndex="1" GridPane.rowIndex="22"/>
<Label text="%settings.emdn.sub" GridPane.rowIndex="22" /> <Label text="%settings.emdn.sub" GridPane.rowIndex="23" />
<TextField fx:id="emdnSubServ" GridPane.columnIndex="1" GridPane.rowIndex="22" /> <TextField fx:id="emdnSubServ" GridPane.columnIndex="1" GridPane.rowIndex="23" />
</GridPane> </GridPane>
</ScrollPane>

View File

@@ -1,5 +1,6 @@
package ru.trader.analysis; package ru.trader.analysis;
import org.jetbrains.annotations.Nullable;
import ru.trader.analysis.graph.Edge; import ru.trader.analysis.graph.Edge;
import ru.trader.core.Offer; import ru.trader.core.Offer;
import ru.trader.core.Vendor; import ru.trader.core.Vendor;
@@ -165,6 +166,7 @@ public class CrawlerSpecificator {
if (res) return true; if (res) return true;
for (TimeEntry<Offer> entry : offers){ for (TimeEntry<Offer> entry : offers){
Offer offer = entry.obj; Offer offer = entry.obj;
if (offer.getVendor().equals(vendor)) return true;
Offer sell = vendor.getSell(offer.getItem()); Offer sell = vendor.getSell(offer.getItem());
res = sell != null && sell.getCount() >= offer.getCount(); res = sell != null && sell.getCount() >= offer.getCount();
if (res) return true; if (res) return true;
@@ -172,12 +174,23 @@ public class CrawlerSpecificator {
return false; return false;
} }
public Collection<Vendor> getVendors(Collection<Vendor> vendors){ public Set<Vendor> getVendors(Collection<Scorer.Rating> vendors){
Set<Vendor> v = containsAny.stream().map(e -> e.obj).collect(Collectors.toSet()); Set<Vendor> v = all.stream().map(e -> e.obj).collect(Collectors.toSet());
any.stream().map(e -> e.obj).forEach(v::add); if (containsAny.size() > 0){
all.stream().map(e -> e.obj).forEach(v::add); vendors.stream().filter(r -> contains(containsAny, r.getVendor())).sorted().limit(5).forEach(r -> v.add(r.getVendor()));
offers.stream().map(e -> e.obj.getVendor()).forEach(v::add); }
v.addAll(vendors); if (any.size() > 0){
vendors.stream().filter(r -> contains(any, r.getVendor())).sorted().limit(5).forEach(r -> v.add(r.getVendor()));
}
for (TimeEntry<Offer> entry : offers) {
vendors.stream().filter(r -> {
Offer offer = entry.obj;
if (offer.getVendor().equals(r.getVendor())) return true;
Offer sell = r.getVendor().getSell(offer.getItem());
return sell != null && sell.getCount() >= offer.getCount();
}).sorted().limit(5).forEach(r -> v.add(r.getVendor()));
}
return v; return v;
} }

View File

@@ -27,70 +27,26 @@ import java.util.stream.Stream;
public class Scorer { public class Scorer {
private final static Logger LOG = LoggerFactory.getLogger(Scorer.class); private final static Logger LOG = LoggerFactory.getLogger(Scorer.class);
private final Map<Item, Offer> sellOffers;
private final Map<Item, Offer> buyOffers;
private final FilteredMarket market; private final FilteredMarket market;
private final Profile profile; private final Profile profile;
private final double avgProfit;
private final double minProfit;
private final double maxProfit;
private final double maxScore;
private final double avgDistance; private final double avgDistance;
public Scorer(FilteredMarket market, Profile profile) { public Scorer(FilteredMarket market, Profile profile) {
this.market = market; this.market = market;
this.profile = profile; this.profile = profile;
sellOffers = new HashMap<>(100, 0.9f);
buyOffers = new HashMap<>(100, 0.9f);
market.getItems().forEach(this::fillOffers);
DoubleSummaryStatistics statProfit = computeProfit();
minProfit = statProfit.getMin() / profile.getShip().getCargo();
avgProfit = statProfit.getAverage() / profile.getShip().getCargo();
maxProfit = statProfit.getMax() / profile.getShip().getCargo();
avgDistance = computeAvgDistance(); avgDistance = computeAvgDistance();
maxScore = getScore(1, statProfit.getMax(), 0, 1, 0, 0);
} }
public Profile getProfile() { public Profile getProfile() {
return profile; return profile;
} }
private void fillOffers(Item item){
Optional<Offer> offer = market.getSell(item).findFirst();
if (offer.isPresent()){
sellOffers.put(item, offer.get());
}
offer = market.getBuy(item).findFirst();
if (offer.isPresent()){
buyOffers.put(item, offer.get());
}
}
private DoubleSummaryStatistics computeProfit(){
return sellOffers.values().stream()
.flatMap(this::mapToOrder)
.collect(Collectors.summarizingDouble(Order::getProfit));
}
private double computeAvgDistance(){ private double computeAvgDistance(){
OptionalDouble res = market.getVendors().mapToDouble(Vendor::getDistance).average(); OptionalDouble res = market.getVendors().mapToDouble(Vendor::getDistance).average();
return res.orElse(0); return res.orElse(0);
} }
public double getAvgProfit() {
return avgProfit;
}
public double getMaxProfit() {
return maxProfit;
}
public double getMaxScore() {
return maxScore;
}
public double getAvgDistance() { public double getAvgDistance() {
return avgDistance; return avgDistance;
} }
@@ -157,6 +113,43 @@ public class Scorer {
return score; return score;
} }
public List<Order> getOrders(Vendor seller, Vendor buyer){
FilteredVendor fSeller = market.getFiltered(seller);
FilteredVendor fBuyer = market.getFiltered(buyer);
return MarketUtils.getOrders(fSeller, fBuyer);
}
public RatingComputer getRatingComputer(final Set<Vendor> vendors){
return new RatingComputer(vendors);
}
public class RatingComputer {
private final Map<Item, Offer> sellOffers;
private final Map<Item, Offer> buyOffers;
private final DoubleSummaryStatistics globalStat;
private final double avgDistance;
private RatingComputer(final Set<Vendor> vendors) {
sellOffers = new HashMap<>(100, 0.9f);
buyOffers = new HashMap<>(100, 0.9f);
market.getItems().forEach(i -> fillOffers(i, vendors));
globalStat = computeProfit();
avgDistance = vendors.stream().mapToDouble(Vendor::getDistance).average().orElse(0);
}
private void fillOffers(Item item, Set<Vendor> vendors){
Optional<Offer> offer = market.getSell(item).filter(o -> vendors.contains(o.getVendor())).findFirst();
if (offer.isPresent()){
sellOffers.put(item, offer.get());
}
offer = market.getBuy(item).filter(o -> vendors.contains(o.getVendor())).findFirst();
if (offer.isPresent()){
buyOffers.put(item, offer.get());
}
}
private Stream<Order> mapToOrder(Offer offer) { private Stream<Order> mapToOrder(Offer offer) {
Offer sell; Offer sell;
Offer buy; Offer buy;
@@ -173,9 +166,60 @@ public class Scorer {
return Stream.of(order); return Stream.of(order);
} }
public List<Order> getOrders(Vendor seller, Vendor buyer){ private DoubleSummaryStatistics computeProfit(){
FilteredVendor fSeller = market.getFiltered(seller); return sellOffers.values().stream()
FilteredVendor fBuyer = market.getFiltered(buyer); .flatMap(this::mapToOrder)
return MarketUtils.getOrders(fSeller, fBuyer); .collect(Collectors.summarizingDouble(Order::getProfit));
}
private DoubleSummaryStatistics computeProfits(Stream<Order> orders) {
return orders.sorted(Comparator.<Order>reverseOrder())
.limit(4)
.filter(o -> o.getProfit() > 0)
.collect(Collectors.summarizingDouble(Order::getProfit));
}
public Rating getRating(Vendor vendor){
Stream<Order> sell = vendor.getAllSellOffers().stream().flatMap(this::mapToOrder);
Stream<Order> buy = vendor.getAllBuyOffers().stream().flatMap(this::mapToOrder);
DoubleSummaryStatistics sellStat = computeProfits(sell);
DoubleSummaryStatistics buyStat = computeProfits(buy);
double sellRate = 0.5 * sellStat.getMax() / globalStat.getMax() + 2.5 * sellStat.getAverage() / globalStat.getAverage();
double buyRate = 0.5 * buyStat.getMax() / globalStat.getMax() + 2 * buyStat.getAverage() / globalStat.getAverage();
double distRate = 0.5 * (vendor.getDistance() > 0 ? (vendor.getDistance() < avgDistance ? 1-vendor.getDistance()/avgDistance : -1+avgDistance/vendor.getDistance()) : 0.0);
LOG.trace("Computed rate for {} = {}", vendor.getFullName(), sellRate + buyRate + distRate);
LOG.trace("global - max: {} avg: {} min: {}", globalStat.getMax(), globalStat.getAverage(), globalStat.getMin());
LOG.trace("sell - max: {} avg: {} min: {} rate: {}", sellStat.getMax(), sellStat.getAverage(), sellStat.getMin(), sellRate);
LOG.trace("buy - max: {} avg: {} min: {} rate: {}", buyStat.getMax(), buyStat.getAverage(), buyStat.getMin(), buyRate);
LOG.trace("distance: {} avg: {} rate: {}", vendor.getDistance(), avgDistance, distRate);
return new Rating(vendor, sellRate + buyRate + distRate);
}
}
public class Rating implements Comparable<Rating> {
private final Vendor vendor;
private final double rate;
public Rating(Vendor vendor, double rate) {
this.vendor = vendor;
this.rate = rate;
}
public Vendor getVendor() {
return vendor;
}
public double getRate() {
return rate;
}
@Override
public int compareTo(Rating o) {
return Double.compare(rate, o.rate);
}
} }
} }

View File

@@ -296,13 +296,26 @@ public class MarketAnalyzer {
private Collection<Vendor> getVendors(CrawlerSpecificator specificator, boolean withTransit){ private Collection<Vendor> getVendors(CrawlerSpecificator specificator, boolean withTransit){
List<Vendor> transits = withTransit ? market.get().map(Place::asTransit).collect(Collectors.toList()) : new ArrayList<>(); List<Vendor> transits = withTransit ? market.get().map(Place::asTransit).collect(Collectors.toList()) : new ArrayList<>();
Collection<Vendor> vendors; Set<Vendor> vendors;
if (!specificator.isFullScan() || specificator.getMinHop() >= profile.getLands()){ if (!specificator.isFullScan() || specificator.getMinHop() >= profile.getLands()){
vendors = market.getMarkets().filter(specificator::contains).collect(Collectors.toList()); vendors = market.getMarkets().filter(specificator::contains).collect(Collectors.toSet());
} else { } else {
vendors = market.getMarkets().collect(Collectors.toList()); vendors = market.getMarkets().collect(Collectors.toSet());
} }
vendors = specificator.getVendors(vendors); Scorer.RatingComputer ratings = searcher.getScorer().getRatingComputer(vendors);
Collection<Scorer.Rating> removes = new ArrayList<>(500);
vendors.removeIf(v -> {
Scorer.Rating rating = ratings.getRating(v);
if (rating.getRate() <= profile.getMinVendorRating()){
if (specificator.contains(v)){
removes.add(rating);
}
return true;
}
return false;
});
vendors.addAll(specificator.getVendors(removes));
vendors.addAll(transits); vendors.addAll(transits);
return vendors; return vendors;
} }

View File

@@ -15,6 +15,7 @@ public class Profile {
private int lands; private int lands;
private boolean refill; private boolean refill;
private int routesCount; private int routesCount;
private double minVendorRating;
//Scorer multipliers //Scorer multipliers
private double distanceTime; private double distanceTime;
private double jumpTime; private double jumpTime;
@@ -31,6 +32,7 @@ public class Profile {
jumps = 3; jumps = 3;
lands = 4; lands = 4;
routesCount = 30; routesCount = 30;
minVendorRating = 7;
distanceTime = 0.3; distanceTime = 0.3;
fuelPrice = 100; fuelPrice = 100;
landingTime = 80; landingTime = 80;
@@ -49,6 +51,7 @@ public class Profile {
this.lands = profile.lands; this.lands = profile.lands;
this.refill = profile.refill; this.refill = profile.refill;
this.routesCount = profile.routesCount; this.routesCount = profile.routesCount;
this.minVendorRating = profile.minVendorRating;
this.distanceTime = profile.distanceTime; this.distanceTime = profile.distanceTime;
this.jumpTime = profile.jumpTime; this.jumpTime = profile.jumpTime;
this.landingTime = profile.landingTime; this.landingTime = profile.landingTime;
@@ -142,6 +145,14 @@ public class Profile {
this.routesCount = routesCount; this.routesCount = routesCount;
} }
public double getMinVendorRating() {
return minVendorRating;
}
public void setMinVendorRating(double minVendorRating) {
this.minVendorRating = minVendorRating;
}
public double getDistanceTime() { public double getDistanceTime() {
return distanceTime; return distanceTime;
} }
@@ -230,6 +241,7 @@ public class Profile {
profile.setLands(Integer.valueOf(values.getProperty("profile.lands", "4"))); profile.setLands(Integer.valueOf(values.getProperty("profile.lands", "4")));
profile.setPathPriority(PATH_PRIORITY.valueOf(values.getProperty("profile.search.priority", "FAST"))); profile.setPathPriority(PATH_PRIORITY.valueOf(values.getProperty("profile.search.priority", "FAST")));
profile.setRoutesCount(Integer.valueOf(values.getProperty("profile.search.routes", "30"))); profile.setRoutesCount(Integer.valueOf(values.getProperty("profile.search.routes", "30")));
profile.setMinVendorRating(Double.valueOf(values.getProperty("profile.search.minRating", "7")));
profile.setFuelPrice(Double.valueOf(values.getProperty("profile.search.fuel.price", "100"))); profile.setFuelPrice(Double.valueOf(values.getProperty("profile.search.fuel.price", "100")));
profile.setDistanceTime(Double.valueOf(values.getProperty("profile.search.times.distance", "0.3"))); profile.setDistanceTime(Double.valueOf(values.getProperty("profile.search.times.distance", "0.3")));
profile.setLandingTime(Double.valueOf(values.getProperty("profile.search.times.landing", "80"))); profile.setLandingTime(Double.valueOf(values.getProperty("profile.search.times.landing", "80")));
@@ -250,6 +262,7 @@ public class Profile {
values.setProperty("profile.lands", String.valueOf(lands)); values.setProperty("profile.lands", String.valueOf(lands));
values.setProperty("profile.search.priority", String.valueOf(pathPriority)); values.setProperty("profile.search.priority", String.valueOf(pathPriority));
values.setProperty("profile.search.routes", String.valueOf(routesCount)); values.setProperty("profile.search.routes", String.valueOf(routesCount));
values.setProperty("profile.search.minRating", String.valueOf(minVendorRating));
values.setProperty("profile.search.fuel.price", String.valueOf(fuelPrice)); values.setProperty("profile.search.fuel.price", String.valueOf(fuelPrice));
values.setProperty("profile.search.times.distance", String.valueOf(distanceTime)); values.setProperty("profile.search.times.distance", String.valueOf(distanceTime));
values.setProperty("profile.search.times.landing", String.valueOf(landingTime)); values.setProperty("profile.search.times.landing", String.valueOf(landingTime));

View File

@@ -36,7 +36,7 @@ public class ScorerTest extends Assert {
profile.setBalance(1000000); profile.setBalance(1000000);
Scorer scorer = new Scorer(fWorld, profile); Scorer scorer = new Scorer(fWorld, profile);
double avgProfit = scorer.getAvgProfit() * profile.getShip().getCargo(); double avgProfit = 750 * profile.getShip().getCargo();
double score = scorer.getScore(scorer.getAvgDistance(), 0, 1, 1, 0, 4); double score = scorer.getScore(scorer.getAvgDistance(), 0, 1, 1, 0, 4);
double score1 = scorer.getScore(scorer.getAvgDistance(), avgProfit/2, 1, 1, 0, 4); double score1 = scorer.getScore(scorer.getAvgDistance(), avgProfit/2, 1, 1, 0, 4);