Archived
0

implement import powerplay data

This commit is contained in:
iMoHax
2016-10-31 17:05:17 +03:00
parent 58de159911
commit dc82317482
6 changed files with 2691 additions and 13 deletions

View File

@@ -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<Place> getNear(Collection<Place> starSystems, Collection<Place> centers, double radius, double maxDistance){
public Collection<Place> getControlling(Place starSystem){
return getControlling(starSystem, market.get(), CONTROLLING_RADIUS);
}
public Collection<Place> getIntersects(Collection<Place> starSystems){
return getIntersects(market.get(), starSystems, CONTROLLING_RADIUS);
}
public Collection<Place> getIntersects(Place starSystem, Collection<Place> starSystems){
return getIntersects(starSystem, market.get(), starSystems, CONTROLLING_RADIUS);
}
public static Collection<Place> getControlling(Place starSystem, Collection<Place> starSystems, double radius){
return starSystems.stream()
.filter(new Controlling(starSystem, radius))
.collect(Collectors.toList());
}
public static Collection<Place> getNear(Collection<Place> starSystems, Collection<Place> 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<Place> getIntersects(Place checkedSystem, Collection<Place> starSystems, Collection<Place> centers, double radius){
public static Collection<Place> getIntersects(Place checkedSystem, Collection<Place> starSystems, Collection<Place> centers, double radius){
return starSystems.stream()
.filter(new FarDropper(centers, radius))
.filter(intersectsPredicate(checkedSystem, centers, radius))
.collect(Collectors.toList());
}
public Collection<Place> getIntersects(Collection<Place> starSystems, Collection<Place> centers, double radius){
public static Collection<Place> getIntersects(Collection<Place> starSystems, Collection<Place> centers, double radius){
return starSystems.stream()
.filter(new FarDropper(centers, radius))
.filter(intersectsPredicate(centers, radius))
.collect(Collectors.toList());
}
private Predicate<Place> intersectsAnyPredicate(Collection<Place> places, double radius){
private static Predicate<Place> intersectsAnyPredicate(Collection<Place> places, double radius){
Predicate<Place> intersects = null;
for (Place place : places) {
if (intersects == null) intersects = new Controlling(place, radius);
@@ -67,7 +83,7 @@ public class PowerPlayAnalyzator {
}
private Predicate<Place> intersectsPredicate(Collection<Place> places, double radius){
private static Predicate<Place> intersectsPredicate(Collection<Place> places, double radius){
Predicate<Place> 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<Place> intersectsPredicate(Place checkedPlace, Collection<Place> places, double radius){
private static Predicate<Place> intersectsPredicate(Place checkedPlace, Collection<Place> places, double radius){
return new Controlling(checkedPlace, radius).and(intersectsAnyPredicate(places, radius));
}
private class Controlling implements Predicate<Place> {
private static class Controlling implements Predicate<Place> {
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<Place> {
private static class FarDropper implements Predicate<Place> {
private double minX;
private double maxX;
private double minY;
@@ -148,7 +165,7 @@ public class PowerPlayAnalyzator {
}
}
private class DistanceComparator implements Comparator<Place> {
private static class DistanceComparator implements Comparator<Place> {
private final Collection<Place> centers;
private final HashMap<Place, Double> distances;

View File

@@ -92,6 +92,7 @@ public enum POWER {
return super.isLegal(faction, item, state);
}
},
GROM,
NONE;
private final static String WEAPONS_GRP="weapons";

View File

@@ -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<PowerData> 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;
}
}
}

View File

@@ -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<Place> intersectsMahon = analyzator.getIntersects(Arrays.asList(opala, gd_319));
Collection<Place> intersectsDuval = analyzator.getIntersects(bolg, Arrays.asList(opala, gd_319));
Collection<Place> exploitedOpala = analyzator.getControlling(opala);
Collection<Place> 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());
}
}

View File

@@ -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",""
1 Id Power Id Value State Upkeep Default Upkeep Current Income Controlstarsystem Id Qty For Qty Against Thr For Thr Against Prediction В 
2 Opala (78755) Edmund Mahon (100010) 7 control 23 23 131 2842 4650 2818 13778 FORTIFY
3 Gui Xian (3932411564754) A. Lavigny-Duval (100020) 10 control 22 0 99 2760 0 2760 15031 FORTIFY
4 Bolg (2871588038081) Aisling Duval (100000) 8 control 24 24 65 6413 0 6213 10701 FORTIFY
5 26 Draconis (2869440619961) Archon Delaine (100100) 6 takingControl 0 0 0 3690 24830 6632 9652 FAIL
6 Gyhldekala (2869977687521) Yuri Grom (100120) 0 control 28 28 108 4993 420 3725 8507 FORTIFY
7 GD 319 (9467584587225) Edmund Mahon (100010) 0 control 0 0 0 Lundji (11666876278233) PASS
8 Ithaca (77805) Edmund Mahon (100010) 5 blocked 22 22 112 1749 2070 5314 18818 PASS

File diff suppressed because it is too large Load Diff