From 242d67b390016c352dc0168572847cbc2f86e174 Mon Sep 17 00:00:00 2001 From: Mo Date: Thu, 26 Jan 2017 20:08:15 +0300 Subject: [PATCH] show radius statistics for every system implement copy to clipboard powerplay datas --- .../controllers/PowerPlayController.java | 235 ++++++++++-------- .../ru/trader/view/support/ViewUtils.java | 30 ++- .../resources/lang/locale_en_US.properties | 16 +- .../resources/lang/locale_ru_RU.properties | 15 +- client/src/main/resources/view/powerplay.fxml | 90 +++++-- client/src/main/resources/view/style.css | 8 + .../trader/analysis/PowerPlayAnalyzator.java | 195 +++++++++++++++ 7 files changed, 457 insertions(+), 132 deletions(-) diff --git a/client/src/main/java/ru/trader/controllers/PowerPlayController.java b/client/src/main/java/ru/trader/controllers/PowerPlayController.java index a2122be..5472118 100644 --- a/client/src/main/java/ru/trader/controllers/PowerPlayController.java +++ b/client/src/main/java/ru/trader/controllers/PowerPlayController.java @@ -1,6 +1,5 @@ package ru.trader.controllers; -import javafx.beans.InvalidationListener; import javafx.beans.property.*; import javafx.collections.FXCollections; import javafx.collections.ObservableList; @@ -16,7 +15,10 @@ import org.slf4j.LoggerFactory; import ru.trader.Main; import ru.trader.analysis.PowerPlayAnalyzator; import ru.trader.core.*; -import ru.trader.model.*; +import ru.trader.model.MarketModel; +import ru.trader.model.ModelFabric; +import ru.trader.model.ProfileModel; +import ru.trader.model.SystemModel; import ru.trader.model.support.BindingsHelper; import ru.trader.view.support.Localization; import ru.trader.view.support.PowerStateStringConverter; @@ -28,8 +30,8 @@ import ru.trader.view.support.autocomplete.SystemsProvider; import java.util.Collection; import java.util.Collections; +import java.util.Map; import java.util.Optional; -import java.util.Set; import java.util.stream.Collectors; public class PowerPlayController { @@ -83,6 +85,9 @@ public class PowerPlayController { private final ObservableList detail = FXCollections.observableArrayList(); private Place detailSystem; + private PowerPlayAnalyzator.ControllingRadiusStat resultStat; + private PowerPlayAnalyzator.ControllingRadiusStat detailStat; + @FXML private void initialize(){ init(); @@ -181,69 +186,6 @@ public class PowerPlayController { } }); tblDetail.setOnDragDetected(new StarSystemDragDetect(tblDetail)); - result.addListener((InvalidationListener) i -> { - resultCCSumm.setText(getCCSummText(result, getSelectedSystems())); - } - ); - detail.addListener((InvalidationListener) i -> { - detailCCSumm.setText(getCCSummText(detail, detailSystem != null ? Collections.singleton(detailSystem) : null)); - } - ); - } - - private String getCCSummText(Collection collection, Collection starSystems){ - String ccFormat = Localization.getString("powerplay.label.summcc"); - String pwCCFormat = Localization.getString("powerplay.label.cc"); - PowerStringConverter converter = new PowerStringConverter(); - Place hq = ModelFabric.get(hqSystem.orElse(null)); - long[] contestedCc = new long[POWER.values().length]; - long[] intersectedCc = new long[POWER.values().length]; - long[] totalCc = new long[POWER.values().length]; - long contested = 0; - long intersected = 0; - long summCc = 0; - for (ResultEntry entry : collection) { - long cc = entry.getCc(); - summCc += cc; - if (entry.getPower() == null || entry.getPowerState() == null) continue; - if (entry.getPowerState() != POWER_STATE.NONE){ - if (hq == null || entry.getPowerState().isContested() || entry.getPower() != hq.getPower()) { - contested += cc; - } - if (hq != null && (entry.getPowerState().isExploited() || entry.getPowerState().isBlocked()) && entry.getPower() == hq.getPower()) { - intersected += cc; - } - Set powers = entry.getControllingSystems().stream().map(Place::getPower).collect(Collectors.toSet()); - if (entry.getPowerState().isContested()){ - for (POWER power : powers){ - contestedCc[power.ordinal()] += cc; - } - } else { - if (entry.getControllingSystems().size()>1){ - intersectedCc[entry.getPower().ordinal()] += cc; - } - if (entry.getPowerState().isControl() || entry.getPowerState().isExploited()) { - totalCc[entry.getPower().ordinal()] += cc; - } - } - } - } - double upkeep = 0; - if (hq != null && starSystems != null){ - for (Place starSystem : starSystems) { - upkeep += starSystem.computeUpkeep(hq); - } - } - - StringBuilder builder = new StringBuilder(); - builder.append(String.format(ccFormat, summCc, contested, summCc - contested, upkeep, intersected, summCc - contested - upkeep - intersected)); - for (int i = 0; i < POWER.values().length; i++) { - if (totalCc[i] > 0 || contestedCc[i] > 0){ - builder.append("\n"); - builder.append(String.format(pwCCFormat, converter.toString(POWER.values()[i]), totalCc[i], contestedCc[i], intersectedCc[i])); - } - } - return builder.toString(); } private void fillDetail(SystemModel detailSystem) { @@ -253,7 +195,7 @@ public class PowerPlayController { if (starSystem != null){ Collection controllings = analyzator.getControlling(starSystem); controllings.add(new PowerPlayAnalyzator.IntersectData(starSystem)); - detail.addAll(BindingsHelper.observableList(controllings, d -> new ResultEntry(d, starSystem))); + toDetail(controllings, starSystem); } } @@ -278,7 +220,7 @@ public class PowerPlayController { result.clear(); if (starSystem != null && !controlls.isEmpty()){ Collection intersects = analyzator.getIntersects(starSystem, controlls); - result.addAll(BindingsHelper.observableList(intersects, d -> new ResultEntry(d, starSystem))); + toResult(intersects, starSystem); } } @@ -290,7 +232,7 @@ public class PowerPlayController { Collection controllings = selectedSystems.isEmpty() ? analyzator.getControlling(starSystem) : analyzator.getControlling(selectedSystems); controllings.add(new PowerPlayAnalyzator.IntersectData(starSystem)); - result.addAll(BindingsHelper.observableList(controllings,d -> new ResultEntry(d, starSystem))); + toResult(controllings, starSystem); } } @@ -299,7 +241,7 @@ public class PowerPlayController { result.clear(); if (!controlls.isEmpty()){ Collection near = analyzator.getNear(controlls); - result.addAll(BindingsHelper.observableList(near, ResultEntry::new)); + toResult(near); } } @@ -309,7 +251,7 @@ public class PowerPlayController { Collection controlls = getControlSystems(); result.clear(); Collection near = analyzator.getMaxProfit(hq, controlls); - result.addAll(BindingsHelper.observableList(near, ResultEntry::new)); + toResult(near); } } @@ -318,19 +260,103 @@ public class PowerPlayController { result.clear(); if (!controlls.isEmpty()){ Collection near = analyzator.getNearExpansions(controlls); - result.addAll(BindingsHelper.observableList(near, ResultEntry::new)); + toResult(near); } } - private void getMaxIntersect(){ + private void getMaxIntersect() { Collection controlls = getControlSystems(); result.clear(); if (!controlls.isEmpty()){ Collection intersect = analyzator.getMaxIntersect(controlls); - result.addAll(BindingsHelper.observableList(intersect, ResultEntry::new)); + toResult(intersect); } } + private void toDetail(Collection datas) { + toDetail(datas, null); + } + + private void toDetail(Collection datas, Place from){ + Place hq = ModelFabric.get(hqSystem.orElse(null)); + Collection places = detailSystem != null ? Collections.singleton(detailSystem) : null; + detailStat = new PowerPlayAnalyzator.ControllingRadiusStat(places, hq, datas); + + if (from != null){ + detail.addAll(BindingsHelper.observableList(datas, d -> new ResultEntry(d, from))); + } else { + detail.addAll(BindingsHelper.observableList(datas, ResultEntry::new)); + } + + detailCCSumm.setText(statToText(detailStat, false)); + } + + + private void toResult(Collection datas) { + toResult(datas, null); + } + + private void toResult(Collection datas, Place from){ + Place hq = ModelFabric.get(hqSystem.orElse(null)); + Collection places = getSelectedSystems(); + resultStat = new PowerPlayAnalyzator.ControllingRadiusStat(places, hq, datas); + + if (from != null){ + result.addAll(BindingsHelper.observableList(datas, d -> new ResultEntry(d, from))); + } else { + result.addAll(BindingsHelper.observableList(datas, ResultEntry::new)); + } + + resultCCSumm.setText(statToText(resultStat, false)); + } + + private String statToText(PowerPlayAnalyzator.ControllingRadiusStat stat, boolean full){ + final String line = Localization.getString("powerplay.text.line"); + + StringBuilder builder = new StringBuilder(); + PowerStringConverter converter = new PowerStringConverter(); + if (full) { + int index = 0; + for (Place place : stat.getStarSystems()) { + if (index++ > 0) builder.append("\n"); + builder.append(place.getName()); + if (stat.getHeadquarter() != null) { + builder.append(" ").append(ViewUtils.distanceToString(place.getDistance(stat.getHeadquarter()))).append(" "); + } + SystemModel model = world.getModeler().get(place); + builder.append(" (").append(ViewUtils.stationsAsStringByType(model.getNearByType(), true)).append(")"); + } + builder.append("\n").append(line).append("\n"); + builder.append(String.format(Localization.getString("powerplay.text.detail"), stat.getIncome(), stat.getUpkeep(), stat.getContest(), + stat.getExploited(), stat.getEnemyExploited(), stat.getBlocked(), stat.getEnemyBlocked(), stat.getCurrentRadiusProfit())); + builder.append("\n").append(line).append("\n"); + builder.append(Localization.getString("powerplay.text.summary.title")).append("\n"); + } + builder.append(String.format(Localization.getString("powerplay.text.summary"), stat.getIncome(), stat.getUpkeep(), stat.getIncome()+stat.getUpkeep(), + stat.getFutureContest(), stat.getFutureExploited(), stat.getFutureRadiusProfit())); + if (full) { + builder.append("\n").append(line).append("\n"); + builder.append(Localization.getString("powerplay.text.contest.title")); + } + builder.append("\n"); + for (Map.Entry entry : stat.getContestStat().entrySet()) { + POWER power = entry.getKey(); + PowerPlayAnalyzator.StarSystemsStat powerStat = entry.getValue(); + builder.append(String.format(Localization.getString("powerplay.text.contest.powers"), converter.toString(power), powerStat.getExploited(), powerStat.getIntersect(), powerStat.getContest())); + builder.append("\n"); + for (Map.Entry systemsStatEntry : stat.getContestStatByStarSystems().entrySet()) { + Place place = systemsStatEntry.getKey(); + if (place.getPower() == power) { + PowerPlayAnalyzator.StarSystemsStat systemStat = systemsStatEntry.getValue(); + builder.append(String.format(Localization.getString("powerplay.text.contest.systems"), place.getName(), systemStat.getExploited(), systemStat.getIntersect(), systemStat.getContest())); + builder.append("\n"); + } + } + } + return builder.toString(); + } + + @FXML private void currentAsChecked(){ checkedSystem.setValue(profile.getSystem()); @@ -460,6 +486,20 @@ public class PowerPlayController { } } + @FXML + private void copyResultStatToClipboard(){ + if (resultStat != null) { + Main.copyToClipboard(statToText(resultStat, true)); + } + } + + @FXML + private void copyDetailStatToClipboard(){ + if (detailStat != null) { + Main.copyToClipboard(statToText(detailStat, true)); + } + } + public class ResultEntry { private final SystemModel starSystem; @@ -473,6 +513,8 @@ public class PowerPlayController { private final ReadOnlyLongProperty currentUpkeep; private final ReadOnlyLongProperty income; private final ReadOnlyDoubleProperty upkeep; + private final ReadOnlyDoubleProperty profit; + private final ReadOnlyLongProperty contested; private final ReadOnlyLongProperty cc; public ResultEntry(PowerPlayAnalyzator.IntersectData data) { @@ -482,7 +524,7 @@ public class PowerPlayController { public ResultEntry(PowerPlayAnalyzator.IntersectData data, Place from) { starSystem = world.getModeler().get(data.getStarSystem()); intersectCount = new SimpleIntegerProperty(data.getCount()); - nearStations = new SimpleStringProperty(getStationsString(starSystem.getNearByType())); + nearStations = new SimpleStringProperty(ViewUtils.stationsAsStringByType(starSystem.getNearByType(), false)); intersecting = new SimpleStringProperty(getControllingString(data.getControllingSystems())); controlling = new SimpleStringProperty(getControllingString(data.getStarSystem())); distance = new SimpleDoubleProperty(from != null ? from.getDistance(data.getStarSystem()) : Double.NaN); @@ -490,9 +532,16 @@ public class PowerPlayController { distanceHQ = new SimpleDoubleProperty(hq != null ? hq.getDistance(data.getStarSystem()) : Double.NaN); population = new SimpleLongProperty(data.getStarSystem().getPopulation()); currentUpkeep = new SimpleLongProperty(data.getStarSystem().getUpkeep()); - upkeep = new SimpleDoubleProperty(hq != null ? data.getStarSystem().computeUpkeep(hq) : Double.NaN); - income = new SimpleLongProperty(data.getStarSystem().getIncome()); cc = new SimpleLongProperty(data.getStarSystem().computeCC()); + + Collection datas = analyzator.getControlling(data.getStarSystem()); + datas.add(new PowerPlayAnalyzator.IntersectData(data.getStarSystem())); + PowerPlayAnalyzator.ControllingRadiusStat stat = new PowerPlayAnalyzator.ControllingRadiusStat(Collections.singleton(data.getStarSystem()), hq, datas); + income = new SimpleLongProperty(stat.getIncome()); + upkeep = new SimpleDoubleProperty(stat.getUpkeep()); + profit = new SimpleDoubleProperty(stat.getFutureRadiusProfit()); + contested = new SimpleLongProperty(stat.getFutureContest()); + } private String getControllingString(Collection controllings) { @@ -515,29 +564,6 @@ public class PowerPlayController { return res.toString(); } - private String getStationsString(Collection stations) { - StringBuilder res = new StringBuilder(); - for (StationModel station : stations) { - if (res.length() != 0) res.append("\n"); - if (station.getType() != null){ - if (station.getType().isPlanetary()) { - res.append("LP"); - } else - if (station.getType().hasLargeLandpad()){ - res.append("L"); - } else { - res.append("M"); - } - } else { - res.append("?"); - } - res.append(" - ").append(station.getName()); - res.append(" (").append(ViewUtils.stationDistanceToString(station.getDistance())).append(")"); - } - return res.toString(); - } - - public ReadOnlyStringProperty nameProperty(){ return starSystem.nameProperty(); } @@ -603,6 +629,14 @@ public class PowerPlayController { return income; } + public ReadOnlyDoubleProperty profitProperty() { + return profit; + } + + public ReadOnlyLongProperty contestedProperty() { + return contested; + } + public ReadOnlyStringProperty nearStationsProperty() { return nearStations; } @@ -616,6 +650,7 @@ public class PowerPlayController { } } + private class StarSystemDragDetect implements EventHandler { private final Node source; diff --git a/client/src/main/java/ru/trader/view/support/ViewUtils.java b/client/src/main/java/ru/trader/view/support/ViewUtils.java index daac09b..4d0aed3 100644 --- a/client/src/main/java/ru/trader/view/support/ViewUtils.java +++ b/client/src/main/java/ru/trader/view/support/ViewUtils.java @@ -9,10 +9,12 @@ import javafx.event.EventHandler; import javafx.scene.control.TableColumn; import javafx.scene.control.TablePosition; import javafx.scene.control.TableView; +import ru.trader.model.StationModel; import javax.swing.*; import java.awt.event.InputEvent; import java.awt.event.KeyEvent; +import java.util.Collection; public class ViewUtils { public static final String ILLEGAL_ITEM_STYLE = "illegal_item"; @@ -102,6 +104,32 @@ public class ViewUtils { public static String fuelToString(double fuel, double tank){ if (tank == 0) return String.format("%.0f t", fuel); - return String.format("%.1f%%", fuel*100 / tank); + return String.format("%.1f%%", fuel * 100 / tank); } + + public static String stationsAsStringByType(Collection stations, boolean inline) { + StringBuilder res = new StringBuilder(); + for (StationModel station : stations) { + if (res.length() != 0){ + if (inline) res.append(", "); + else res.append("\n"); + } + if (station.getType() != null){ + if (station.getType().isPlanetary()) { + res.append("LP"); + } else + if (station.getType().hasLargeLandpad()){ + res.append("L"); + } else { + res.append("M"); + } + } else { + res.append("?"); + } + res.append(" - ").append(station.getName()); + res.append(" (").append(stationDistanceToString(station.getDistance())).append(")"); + } + return res.toString(); + } + } diff --git a/client/src/main/resources/lang/locale_en_US.properties b/client/src/main/resources/lang/locale_en_US.properties index 47a22fa..c021e45 100644 --- a/client/src/main/resources/lang/locale_en_US.properties +++ b/client/src/main/resources/lang/locale_en_US.properties @@ -27,6 +27,8 @@ market.system=System market.system.name=Name market.system.income=Income market.system.upkeep=Upkeep +market.system.profit=Profit +market.system.contested=Contested market.system.controlling=Controlled #Station @@ -287,8 +289,18 @@ powerplay.label.controlling=Controlled systems: powerplay.label.power.systems=Systems of Power: powerplay.label.power.state=State: powerplay.label.populationSumm=Summ populations: -powerplay.label.cc=%s: %4d CC Contested: %4d CC Intersected: %4d CC -powerplay.label.summcc=Summ: %5d CC Contested: %5d CC Income: %5d CC\nUpkeep: %5.0f CC Already exploited: %5d CC Total: %5.0f CC +powerplay.text.line=------------------------------------------- +powerplay.text.detail=Current stat:\n\ + Income: %4d \u041A\u041A Upkeep: %4.0f \u041A\u041A Contested: %4d \u041A\u041A\n\ + Our exploited: %4d \u041A\u041A Others exploited: %4d \u041A\u041A\n\ + Our blocked: %4d \u041A\u041A Others blocked: %4d \u041A\u041A Total: %4.0f \u041A\u041A +powerplay.text.summary.title=After expansion complete: +powerplay.text.summary=\ + Income: %4d \u041A\u041A Upkeep: %4.0f \u041A\u041A Expansion cost: %4.0f \u041A\u041A\n\ + Contested: %4d \u041A\u041A Our exploited: %4d \u041A\u041A Total: %4.0f \u041A\u041A +powerplay.text.contest.title=Contested: +powerplay.text.contest.powers=%-20s - %4d \u041A\u041A, Intersected: %4d \u041A\u041A, Contested: %4d \u041A\u041A +powerplay.text.contest.systems=\ %19s - %4d \u041A\u041A, Intersected: %4d \u041A\u041A, Contested: %4d \u041A\u041A powerplay.result.title=Analyze result powerplay.column.intersecting=Intersect powerplay.column.intersectCount=Intersect count diff --git a/client/src/main/resources/lang/locale_ru_RU.properties b/client/src/main/resources/lang/locale_ru_RU.properties index 990d0f2..ae41da3 100644 --- a/client/src/main/resources/lang/locale_ru_RU.properties +++ b/client/src/main/resources/lang/locale_ru_RU.properties @@ -25,8 +25,10 @@ market.group=\u0413\u0440\u0443\u043F\u043F\u0430 #System market.system=\u0421\u0438\u0441\u0442\u0435\u043C\u0430 market.system.name=\u041D\u0430\u0437\u0432\u0430\u043D\u0438\u0435 -market.system.income=Income -market.system.upkeep=Upkeep +market.system.income=\u0414\u043E\u0445\u043E\u0434 +market.system.upkeep=\u0421\u043E\u0434\u0435\u0440\u0436\u0430\u043D\u0438\u0435 +market.system.profit=\u041F\u0440\u0438\u0431\u044B\u043B\u044C +market.system.contested=\u041E\u0441\u043F\u0430\u0440\u0438\u0432\u0430\u0435\u0442\u0441\u044F market.system.controlling=\u041A\u043E\u043D\u0442\u0440\u043E\u043B\u0438\u0440\u0443\u0435\u0442\u0441\u044F #Station @@ -287,8 +289,13 @@ powerplay.label.controlling=\u041A\u043E\u043D\u0442\u0440\u043E\u043B\u043B\u04 powerplay.label.power.systems=C\u0438\u0441\u0442\u0435\u043C\u044B \u0441\u0438\u043B\u044B: powerplay.label.power.state=\u0421\u043E\u0441\u0442\u043E\u044F\u043D\u0438\u0435: powerplay.label.populationSumm=\u0421\u0443\u043C\u043C\u0430 \u043D\u0430\u0441\u0435\u043B\u0435\u043D\u0438\u044F: -powerplay.label.cc=%s: %4d \u041A\u041A \u041E\u0441\u043F\u0430\u0440\u0438\u0432\u0430\u0435\u043C\u044B\u0445: %4d \u041A\u041A \u041F\u0435\u0440\u0435\u0441\u0435\u043A\u0430\u044E\u0449\u0438\u0445\u0441\u044F: %4d \u041A\u041A -powerplay.label.summcc=\u0421\u0443\u043C\u043C\u0430: %5d \u041A\u041A \u041E\u0441\u043F\u0430\u0440\u0438\u0432\u0430\u0435\u043C\u044B\u0445: %5d \u041A\u041A \u0414\u043E\u0445\u043E\u0434: %5d \u041A\u041A\n\u0420\u0430\u0441\u0445\u043E\u0434\u044B: %5.0f \u041A\u041A \u0423\u0436\u0435 \u044D\u043A\u0441\u043F\u043B\u0443\u0430\u0442\u0438\u0440\u0443\u0435\u043C\u044B\u0445: %5d \u041A\u041A \u0418\u0442\u043E\u0433\u043E: %5.0f \u041A\u041A +powerplay.text.line=------------------------------------------- +powerplay.text.detail=\u041D\u0430 \u0434\u0430\u043D\u043D\u044B\u0439 \u043C\u043E\u043C\u0435\u043D\u0442:\n\u0414\u043E\u0445\u043E\u0434: %4d \u041A\u041A \u0421\u043E\u0434\u0435\u0440\u0436\u0430\u043D\u0438\u0435: %4.0f \u041A\u041A \u041E\u0441\u043F\u0430\u0440\u0438\u0432\u0430\u0435\u043C\u044B\u0445: %4d \u041A\u041A\n\u042D\u043A\u0441\u043B\u0443\u0430\u0442\u0438\u0440\u0443\u0435\u043C\u044B\u0445 \u043D\u0430\u043C\u0438: %4d \u041A\u041A \u042D\u043A\u0441\u043B\u0443\u0430\u0442\u0438\u0440\u0443\u0435\u043C\u044B\u0445 \u0434\u0440\u0443\u0433\u0438\u043C\u0438: %4d \u041A\u041A\n\u0411\u043B\u043E\u043A\u0438\u0440\u043E\u0432\u0430\u043D\u043E \u043D\u0430\u043C\u0438: %4d \u041A\u041A \u0411\u043B\u043E\u043A\u0438\u0440\u043E\u0432\u0430\u043D\u043E \u0434\u0440\u0443\u0433\u0438\u043C\u0438: %4d \u041A\u041A \u0418\u0442\u043E\u0433\u043E: %4.0f \u041A\u041A +powerplay.text.summary.title=\u041F\u043E\u0441\u043B\u0435 \u0432\u0437\u044F\u0442\u0438\u044F: +powerplay.text.summary=\u0414\u043E\u0445\u043E\u0434: %4d \u041A\u041A \u0421\u043E\u0434\u0435\u0440\u0436\u0430\u043D\u0438\u0435: %4.0f \u041A\u041A \u0421\u0442\u043E\u0438\u043C\u043E\u0441\u0442\u044C \u044D\u043A\u0441\u043F\u0430\u043D\u0441\u0438\u0438: %4.0f \u041A\u041A\n\u041E\u0441\u043F\u0430\u0440\u0438\u0432\u0430\u0435\u043C\u044B\u0445: %4d \u041A\u041A \u042D\u043A\u0441\u043B\u0443\u0430\u0442\u0438\u0440\u0443\u0435\u043C\u044B\u0445 \u043D\u0430\u043C\u0438: %4d \u041A\u041A \u0418\u0442\u043E\u0433\u043E: %4.0f \u041A\u041A +powerplay.text.contest.title=\u0421\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043A\u0430 \u043F\u043E \u043E\u0441\u043F\u0430\u0440\u0438\u0432\u0430\u0435\u043C\u044B\u043C: +powerplay.text.contest.powers=%-20s - %4d \u041A\u041A, \u041F\u0435\u0440\u0435\u0441\u0435\u043A\u0430\u044E\u0449\u0438\u0445\u0441\u044F: %4d \u041A\u041A, \u041E\u0441\u043F\u0430\u0440\u0438\u0432\u0430\u0435\u043C\u044B\u0445: %4d \u041A\u041A +powerplay.text.contest.systems=\ %19s - %4d \u041A\u041A, \u041F\u0435\u0440\u0435\u0441\u0435\u043A\u0430\u044E\u0449\u0438\u0445\u0441\u044F: %4d \u041A\u041A, \u041E\u0441\u043F\u0430\u0440\u0438\u0432\u0430\u0435\u043C\u044B\u0445: %4d \u041A\u041A powerplay.result.title=\u0420\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442\u044B \u0430\u043D\u0430\u043B\u0438\u0437\u0430 powerplay.column.intersecting=\u041F\u0435\u0440\u0435\u0441\u0435\u043A\u0430\u0435\u0442\u0441\u044F \u0441 powerplay.column.intersectCount=\u041F\u0435\u0440\u0435\u0441\u0435\u0447\u0435\u043D\u0438\u0439 diff --git a/client/src/main/resources/view/powerplay.fxml b/client/src/main/resources/view/powerplay.fxml index 0a8ba31..d6ab4d0 100644 --- a/client/src/main/resources/view/powerplay.fxml +++ b/client/src/main/resources/view/powerplay.fxml @@ -94,11 +94,26 @@ - - + + - - + + + + + + + + + + + + + + + + + @@ -116,6 +131,12 @@ + + + + + + @@ -123,35 +144,32 @@ - - - - - - - - - - - - - - + - + + + @@ -173,6 +191,9 @@ + + + @@ -181,14 +202,23 @@ - - - - + + + + + + + + + + + + + @@ -203,9 +233,19 @@ - + - + + + diff --git a/client/src/main/resources/view/style.css b/client/src/main/resources/view/style.css index 46dad4d..26771f7 100644 --- a/client/src/main/resources/view/style.css +++ b/client/src/main/resources/view/style.css @@ -252,4 +252,12 @@ HBox.fields-group hbox-margin{ .dragged { -fx-base: darkblue; +} + +#resultCCSumm { + -fx-font-family: monospace; +} + +#detailCCSumm { + -fx-font-family: monospace; } \ No newline at end of file diff --git a/core/src/main/java/ru/trader/analysis/PowerPlayAnalyzator.java b/core/src/main/java/ru/trader/analysis/PowerPlayAnalyzator.java index 5a5543c..c199103 100644 --- a/core/src/main/java/ru/trader/analysis/PowerPlayAnalyzator.java +++ b/core/src/main/java/ru/trader/analysis/PowerPlayAnalyzator.java @@ -431,5 +431,200 @@ public class PowerPlayAnalyzator { } } + public static class ControllingRadiusStat { + private final Collection starSystems; + private final Place headquarter; + private long income; + private double upkeep; + private long contest; + private long exploited; + private long enemyExploited; + private long blocked; + private long enemyBlocked; + + Map contestStat; + Map contestStatByStarSystems; + + + public ControllingRadiusStat(Collection starSystems, Place headquarter, Collection exploitedSystems) { + this.starSystems = starSystems; + this.headquarter = headquarter; + contestStat = new HashMap<>(); + contestStatByStarSystems = new HashMap<>(); + fillStat(exploitedSystems); + } + + private void fillStat(Collection exploitedSystems) { + income = 0; contest = 0; exploited = 0; enemyExploited = 0; blocked = 0; enemyBlocked = 0; upkeep = 0; + if (headquarter != null && starSystems != null){ + for (Place starSystem : starSystems) { + upkeep += starSystem.computeUpkeep(headquarter); + } + } + contestStat.clear(); + contestStatByStarSystems.clear(); + for (IntersectData exploitedSystem : exploitedSystems) { + long cc = exploitedSystem.getStarSystem().computeCC(); + income += cc; + POWER power = exploitedSystem.getStarSystem().getPower(); + POWER_STATE state = exploitedSystem.getStarSystem().getPowerState(); + if (state == null) continue; + if (state.isExploited() || state.isControl()){ + if (headquarter != null && headquarter.getPower() == power){ + exploited += cc; + } else { + enemyExploited += cc; + } + } else + if (state.isExpansion() || state.isBlocked()){ + if (headquarter != null && headquarter.getPower() == power){ + blocked += cc; + } else { + enemyBlocked += cc; + } + } else + if (state.isContested()){ + contest += cc; + } + + Set powers = EnumSet.noneOf(POWER.class); + for (Place system : exploitedSystem.getStarSystem().getControllingSystems()) { + powers.add(system.getPower()); + StarSystemsStat stat = contestStatByStarSystems.get(system); + if (stat == null){ + stat = new StarSystemsStat(); + contestStatByStarSystems.put(system, stat); + } + stat.put(exploitedSystem.getStarSystem()); + } + if (state.isControl()){ + Place system = exploitedSystem.getStarSystem(); + powers.add(system.getPower()); + StarSystemsStat stat = contestStatByStarSystems.get(system); + if (stat == null){ + stat = new StarSystemsStat(); + contestStatByStarSystems.put(system, stat); + } + stat.put(exploitedSystem.getStarSystem()); + } + for (POWER p : powers) { + StarSystemsStat stat = contestStat.get(p); + if (stat == null){ + stat = new StarSystemsStat(); + contestStat.put(p, stat); + } + stat.put(exploitedSystem.getStarSystem()); + } + } + } + + public Collection getStarSystems() { + return starSystems; + } + + public Place getHeadquarter() { + return headquarter; + } + + public long getIncome() { + return income; + } + + public double getUpkeep() { + return upkeep; + } + + public long getContest() { + return contest; + } + + public long getExploited() { + return exploited; + } + + public long getEnemyExploited() { + return enemyExploited; + } + + public long getBlocked() { + return blocked; + } + + public long getEnemyBlocked() { + return enemyBlocked; + } + + public double getCurrentRadiusProfit(){ + return income - upkeep - contest - enemyExploited - exploited; + } + + public double getFutureRadiusProfit(){ + return income - upkeep - getFutureContest() - getFutureExploited(); + } + + public long getFutureContest(){ + return contest + enemyExploited + enemyBlocked; + } + + public long getFutureExploited(){ + return exploited + blocked; + } + + public Map getContestStat() { + return contestStat; + } + + public Map getContestStatByStarSystems() { + return contestStatByStarSystems; + } + } + + public static class StarSystemsStat { + private long income; + private long contest; + private long intersect; + private long blocked; + private long exploited; + + public void put(Place starSystem){ + long cc = starSystem.computeCC(); + income += cc; + if (starSystem.getPowerState() != null){ + if (starSystem.getPowerState().isExploited() || starSystem.getPowerState().isControl()){ + exploited += cc; + if (starSystem.getControllingSystems().size() > 1){ + intersect += cc; + } + } else + if (starSystem.getPowerState().isContested()){ + contest += cc; + } else + if (starSystem.getPowerState().isBlocked() || starSystem.getPowerState().isExpansion()){ + blocked += cc; + } + } + } + + public long getIncome() { + return income; + } + + public long getExploited() { + return exploited; + } + + public long getContest() { + return contest; + } + + public long getIntersect() { + return intersect; + } + + public long getBlocked() { + return blocked; + } + } + }