From dc823174824b428504bff2a4ab9d53103daba2bb Mon Sep 17 00:00:00 2001 From: iMoHax Date: Mon, 31 Oct 2016 17:05:17 +0300 Subject: [PATCH] implement import powerplay data --- .../trader/analysis/PowerPlayAnalyzator.java | 43 +- core/src/main/java/ru/trader/core/POWER.java | 1 + .../java/ru/trader/powerplay/PPParser.java | 184 ++ .../ru/trader/powerplay/PPImportTest.java | 87 + utils/src/test/resources/pp.csv | 8 + utils/src/test/resources/world.xml | 2381 +++++++++++++++++ 6 files changed, 2691 insertions(+), 13 deletions(-) create mode 100644 utils/src/main/java/ru/trader/powerplay/PPParser.java create mode 100644 utils/src/test/java/ru/trader/powerplay/PPImportTest.java create mode 100644 utils/src/test/resources/pp.csv create mode 100644 utils/src/test/resources/world.xml diff --git a/core/src/main/java/ru/trader/analysis/PowerPlayAnalyzator.java b/core/src/main/java/ru/trader/analysis/PowerPlayAnalyzator.java index 4881992..5d2509e 100644 --- a/core/src/main/java/ru/trader/analysis/PowerPlayAnalyzator.java +++ b/core/src/main/java/ru/trader/analysis/PowerPlayAnalyzator.java @@ -6,7 +6,6 @@ import ru.trader.core.Market; import ru.trader.core.Place; import ru.trader.core.StarSystemFilter; -import java.util.ArrayList; import java.util.Collection; import java.util.Comparator; import java.util.HashMap; @@ -32,7 +31,27 @@ public class PowerPlayAnalyzator { this.starSystemFilter = starSystemFilter; } - public Collection getNear(Collection starSystems, Collection centers, double radius, double maxDistance){ + public Collection getControlling(Place starSystem){ + return getControlling(starSystem, market.get(), CONTROLLING_RADIUS); + } + + public Collection getIntersects(Collection starSystems){ + return getIntersects(market.get(), starSystems, CONTROLLING_RADIUS); + } + + public Collection getIntersects(Place starSystem, Collection starSystems){ + return getIntersects(starSystem, market.get(), starSystems, CONTROLLING_RADIUS); + } + + + public static Collection getControlling(Place starSystem, Collection starSystems, double radius){ + return starSystems.stream() + .filter(new Controlling(starSystem, radius)) + .collect(Collectors.toList()); + } + + + public static Collection getNear(Collection starSystems, Collection centers, double radius, double maxDistance){ return starSystems.stream() .filter(new FarDropper(centers, maxDistance)) .filter(intersectsAnyPredicate(centers, radius).negate()) @@ -40,24 +59,21 @@ public class PowerPlayAnalyzator { .collect(Collectors.toList()); } - - - - public Collection getIntersects(Place checkedSystem, Collection starSystems, Collection centers, double radius){ + public static Collection getIntersects(Place checkedSystem, Collection starSystems, Collection centers, double radius){ return starSystems.stream() .filter(new FarDropper(centers, radius)) .filter(intersectsPredicate(checkedSystem, centers, radius)) .collect(Collectors.toList()); } - public Collection getIntersects(Collection starSystems, Collection centers, double radius){ + public static Collection getIntersects(Collection starSystems, Collection centers, double radius){ return starSystems.stream() .filter(new FarDropper(centers, radius)) .filter(intersectsPredicate(centers, radius)) .collect(Collectors.toList()); } - private Predicate intersectsAnyPredicate(Collection places, double radius){ + private static Predicate intersectsAnyPredicate(Collection places, double radius){ Predicate intersects = null; for (Place place : places) { if (intersects == null) intersects = new Controlling(place, radius); @@ -67,7 +83,7 @@ public class PowerPlayAnalyzator { } - private Predicate intersectsPredicate(Collection places, double radius){ + private static Predicate intersectsPredicate(Collection places, double radius){ Predicate intersects = null; for (Place place : places) { if (intersects == null) intersects = new Controlling(place, radius); @@ -76,11 +92,11 @@ public class PowerPlayAnalyzator { return intersects; } - private Predicate intersectsPredicate(Place checkedPlace, Collection places, double radius){ + private static Predicate intersectsPredicate(Place checkedPlace, Collection places, double radius){ return new Controlling(checkedPlace, radius).and(intersectsAnyPredicate(places, radius)); } - private class Controlling implements Predicate { + private static class Controlling implements Predicate { private final Place center; private final double radius; @@ -91,6 +107,7 @@ public class PowerPlayAnalyzator { @Override public boolean test(Place place) { + if (place == center) return false; double distance = center.getDistance(place); LOG.trace("Check {}, distance to {} = {}, radius = {}", place, center, distance, radius); return distance <= radius; @@ -98,7 +115,7 @@ public class PowerPlayAnalyzator { } - private class FarDropper implements Predicate { + private static class FarDropper implements Predicate { private double minX; private double maxX; private double minY; @@ -148,7 +165,7 @@ public class PowerPlayAnalyzator { } } - private class DistanceComparator implements Comparator { + private static class DistanceComparator implements Comparator { private final Collection centers; private final HashMap distances; diff --git a/core/src/main/java/ru/trader/core/POWER.java b/core/src/main/java/ru/trader/core/POWER.java index 7cc3374..1a2d1d0 100644 --- a/core/src/main/java/ru/trader/core/POWER.java +++ b/core/src/main/java/ru/trader/core/POWER.java @@ -92,6 +92,7 @@ public enum POWER { return super.isLegal(faction, item, state); } }, + GROM, NONE; private final static String WEAPONS_GRP="weapons"; diff --git a/utils/src/main/java/ru/trader/powerplay/PPParser.java b/utils/src/main/java/ru/trader/powerplay/PPParser.java new file mode 100644 index 0000000..695d734 --- /dev/null +++ b/utils/src/main/java/ru/trader/powerplay/PPParser.java @@ -0,0 +1,184 @@ +package ru.trader.powerplay; + +import au.com.bytecode.opencsv.CSVParser; +import org.jetbrains.annotations.Nullable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import ru.trader.core.*; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class PPParser { + private final static Logger LOG = LoggerFactory.getLogger(PPParser.class); + + private final CSVParser parser; + private final Market market; + private boolean canceled; + private final Collection controllingSystems; + + public PPParser(Market market) { + this.market = market; + parser = new CSVParser(',', '\"'); + controllingSystems = new ArrayList<>(100); + } + + public void cancel(){ + this.canceled = true; + } + + public void parseSystems(File file) throws IOException { + parseFile(file, 1, FILE_TYPE.SYSTEMS); + } + + private void parseFile(File file, int skip, FILE_TYPE type) throws IOException { + canceled = false; + try (BufferedReader reader = new BufferedReader(new FileReader(file))) { + int row = 0; + String line; + while ((line = reader.readLine()) != null) { + if (canceled) break; + row++; + if (row <= skip) continue; + String[] values = parser.parseLine(line); + switch (type) { + case SYSTEMS: parseSystemsFile(values); + break; + case PREPARE: + break; + } + } + if (type == FILE_TYPE.SYSTEMS){ + updatePowerState(); + } + } finally { + if (type == FILE_TYPE.SYSTEMS){ + controllingSystems.clear(); + } + } + } + + public void parseSystemsFile(String[] values) { + // "Id","Power Id","Value","State","Upkeep Default","Upkeep Current","Income","Controlstarsystem Id","Qty For","Qty Against","Thr For","Thr Against","Prediction","В " + String starSystemName = getName(values[0]); + POWER power = getPower(values[1]); + POWER_STATE state = getState(values[3]); + if (starSystemName == null || power == null || state == null) return; + if (state == POWER_STATE.CONTROL || state == POWER_STATE.EXPANSION){ + Place place = market.get(starSystemName); + if (place != null){ + controllingSystems.add(new PowerData(place, power, state)); + } else { + LOG.warn("Not found system {} for import powerplay data", starSystemName); + } + } + } + + + + private final static Pattern NAME_REGEXP = Pattern.compile("(.+)\\s+\\((\\d+)\\)"); + @Nullable + private String getName(String value) { + Matcher matcher = NAME_REGEXP.matcher(value); + if (matcher.find()){ + return matcher.group(1); + } else { + LOG.warn("Unknown format of name: {} ", value); + return null; + } + } + + @Nullable + private POWER getPower(String value) { + String name = getName(value); + if (name == null) return null; + switch (name){ + case "A. Lavigny-Duval": return POWER.LAVIGNY_DUVAL; + case "Aisling Duval": return POWER.DUVAL; + case "Archon Delaine": return POWER.DELAINE; + case "Denton Patreus": return POWER.PATREUS; + case "Edmund Mahon": return POWER.MAHON; + case "Felicia Winters": return POWER.WINTERS; + case "Li Yong-Rui": return POWER.YONG_RUI; + case "Pranav Antal": return POWER.ANTAL; + case "Yuri Grom": return POWER.GROM; + case "Zachary Hudson": return POWER.HUDSON; + case "Zemina Torval": return POWER.TORVAL; + default: + LOG.warn("Unknown power name: {}", name); + } + return null; + } + + @Nullable + private POWER_STATE getState(String value) { + if (value == null) return null; + switch (value){ + case "blocked": return POWER_STATE.NONE; + case "control": return POWER_STATE.CONTROL; + case "contested": return POWER_STATE.CONTESTED; + case "takingControl": return POWER_STATE.EXPANSION; + case "turmoil": return POWER_STATE.NONE; + default: + LOG.warn("Unknown power state: {}", value); + } + return null; + } + + private final static double CONTROLLING_RADIUS = 15; + private void updatePowerState(){ + if (controllingSystems.isEmpty()) return; + for (Place starSystem : market.get()) { + if (starSystem.getFaction() == FACTION.NONE) continue; + if (starSystem.getPowerState() != POWER_STATE.HEADQUARTERS){ + starSystem.setPower(POWER.NONE, POWER_STATE.NONE); + } + for (PowerData powerData : controllingSystems){ + if (starSystem.equals(powerData.starSystem)){ + if (starSystem.getPowerState() != POWER_STATE.HEADQUARTERS){ + starSystem.setPower(powerData.power, powerData.state); + } + } else { + if (powerData.state != POWER_STATE.CONTROL) continue; + if (starSystem.getDistance(powerData.starSystem) <= CONTROLLING_RADIUS){ + if (starSystem.getPowerState() == POWER_STATE.EXPLOITED){ + if (starSystem.getPower() != powerData.power){ + starSystem.setPower(powerData.power, POWER_STATE.CONTESTED); + break; + } + } else { + if (starSystem.getPowerState() == POWER_STATE.NONE){ + starSystem.setPower(powerData.power, POWER_STATE.EXPLOITED); + } else { + LOG.warn("Illegal power state: {}, star system: {}", starSystem.getPower(), starSystem.getName()); + } + } + } + } + } + } + } + + private enum FILE_TYPE { + SYSTEMS, PREPARE + } + + private class PowerData { + private final Place starSystem; + private final POWER power; + private final POWER_STATE state; + + private PowerData(Place starSystem, POWER power, POWER_STATE state) { + this.starSystem = starSystem; + this.power = power; + this.state = state; + } + } + +} diff --git a/utils/src/test/java/ru/trader/powerplay/PPImportTest.java b/utils/src/test/java/ru/trader/powerplay/PPImportTest.java new file mode 100644 index 0000000..100ca77 --- /dev/null +++ b/utils/src/test/java/ru/trader/powerplay/PPImportTest.java @@ -0,0 +1,87 @@ +package ru.trader.powerplay; + +import org.junit.Assert; +import org.junit.Test; +import ru.trader.analysis.PowerPlayAnalyzator; +import ru.trader.core.Market; +import ru.trader.core.POWER; +import ru.trader.core.POWER_STATE; +import ru.trader.core.Place; +import ru.trader.store.simple.Store; + +import java.io.File; +import java.io.InputStream; +import java.util.Arrays; +import java.util.Collection; + +public class PPImportTest extends Assert { + + @Test + public void testImportSystems() throws Exception { + InputStream is = getClass().getResourceAsStream("/world.xml"); + Market market = Store.loadFromFile(is); + Place opala = market.get("Opala"); + Place aulin = market.get("Aulin"); + Place draconis = market.get("26 Draconis"); + Place bolg = market.get("Bolg"); + Place aulis = market.get("Aulis"); + Place lhs2887 = market.get("LHS 2887"); + Place gd_319 = market.get("GD 319"); + + aulin.setPower(POWER.GROM, POWER_STATE.CONTROL); + draconis.setPower(POWER.PATREUS, POWER_STATE.EXPLOITED); + + PPParser parser = new PPParser(market); + parser.parseSystems(new File(getClass().getResource("/pp.csv").getFile())); + + assertEquals(POWER_STATE.CONTROL, opala.getPowerState()); + assertEquals(POWER.MAHON, opala.getPower()); + assertEquals(POWER_STATE.CONTROL, bolg.getPowerState()); + assertEquals(POWER.DUVAL, bolg.getPower()); + + PowerPlayAnalyzator analyzator = new PowerPlayAnalyzator(market); + + Collection intersectsMahon = analyzator.getIntersects(Arrays.asList(opala, gd_319)); + Collection intersectsDuval = analyzator.getIntersects(bolg, Arrays.asList(opala, gd_319)); + + Collection exploitedOpala = analyzator.getControlling(opala); + Collection exploitedBolg = analyzator.getControlling(bolg); + + for (Place place : intersectsMahon) { + assertEquals(POWER_STATE.EXPLOITED, place.getPowerState()); + assertEquals(POWER.MAHON, place.getPower()); + } + + for (Place place : exploitedOpala) { + if (intersectsDuval.contains(place)){ + assertEquals(POWER_STATE.CONTESTED, place.getPowerState()); + } else { + assertEquals(POWER_STATE.EXPLOITED, place.getPowerState()); + assertEquals(POWER.MAHON, place.getPower()); + } + } + + for (Place place : exploitedBolg) { + if (intersectsDuval.contains(place)){ + assertEquals(POWER_STATE.CONTESTED, place.getPowerState()); + } else { + assertEquals(POWER_STATE.EXPLOITED, place.getPowerState()); + assertEquals(POWER.DUVAL, place.getPower()); + } + } + + assertEquals(POWER_STATE.CONTESTED, aulin.getPowerState()); + assertEquals(POWER.DUVAL, aulin.getPower()); + + assertEquals(POWER_STATE.EXPLOITED, aulis.getPowerState()); + assertEquals(POWER.MAHON, aulis.getPower()); + + assertEquals(POWER_STATE.EXPLOITED, lhs2887.getPowerState()); + assertEquals(POWER.DUVAL, lhs2887.getPower()); + + assertEquals(POWER_STATE.EXPANSION, draconis.getPowerState()); + assertEquals(POWER.DELAINE, draconis.getPower()); + + } + +} diff --git a/utils/src/test/resources/pp.csv b/utils/src/test/resources/pp.csv new file mode 100644 index 0000000..20c42f3 --- /dev/null +++ b/utils/src/test/resources/pp.csv @@ -0,0 +1,8 @@ +"Id","Power Id","Value","State","Upkeep Default","Upkeep Current","Income","Controlstarsystem Id","Qty For","Qty Against","Thr For","Thr Against","Prediction","В " +"Opala (78755)","Edmund Mahon (100010)","7","control","23","23","131","","2842","4650","2818","13778","FORTIFY","" +"Gui Xian (3932411564754)","A. Lavigny-Duval (100020)","10","control","22","0","99","","2760","0","2760","15031","FORTIFY","" +"Bolg (2871588038081)","Aisling Duval (100000)","8","control","24","24","65","","6413","0","6213","10701","FORTIFY","" +"26 Draconis (2869440619961)","Archon Delaine (100100)","6","takingControl","0","0","0","","3690","24830","6632","9652","FAIL","" +"Gyhldekala (2869977687521)","Yuri Grom (100120)","0","control","28","28","108","","4993","420","3725","8507","FORTIFY","" +"GD 319 (9467584587225)","Edmund Mahon (100010)","0","control","0","0","0","Lundji (11666876278233)","","","","","PASS","" +"Ithaca (77805)","Edmund Mahon (100010)","5","blocked","22","22","112","","1749","2070","5314","18818","PASS","" diff --git a/utils/src/test/resources/world.xml b/utils/src/test/resources/world.xml new file mode 100644 index 0000000..b50d510 --- /dev/null +++ b/utils/src/test/resources/world.xml @@ -0,0 +1,2381 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file