package polly.rx.parsing;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Scanner;
import java.util.regex.Pattern;
import polly.rx.MSG;
import polly.rx.entities.BattleDrop;
import polly.rx.entities.BattleReport;
import polly.rx.entities.BattleReportShip;
import polly.rx.entities.BattleTactic;
import polly.rx.entities.RxRessource;
import de.skuzzle.polly.sdk.time.Milliseconds;
import de.skuzzle.polly.sdk.time.Time;
public class QBattleReportParser {
// TEST
public static void main(String[] args) throws IOException, ParseException {
final String fileName = "liveKB.txt"; //$NON-NLS-1$
try (InputStream is = QBattleReportParser.class.getResourceAsStream(fileName)) {
final BufferedReader r = new BufferedReader(new InputStreamReader(is, "UTF-8")); //$NON-NLS-1$
final StringBuilder b = new StringBuilder();
String line = null;
while ((line = r.readLine()) != null) {
b.append(line);
b.append("\n"); //$NON-NLS-1$
}
parse(b.toString(), 0);
}
}
private final static DateFormat getDateFormat() {
return new SimpleDateFormat("HH:mm dd-MM-yyyy"); //$NON-NLS-1$
}
public static BattleReport parse(String report, int submitterId) throws ParseException {
try (Scanner s = new Scanner(report)) {
final Pattern delimiter = s.delimiter();
s.useLocale(Locale.ENGLISH);
// date
final DateFormat df = getDateFormat();
Date date;
try {
date = df.parse(s.nextLine().trim());
// round to minutes
long d = date.getTime() / Milliseconds.fromMinutes(1) * Milliseconds.fromMinutes(1);
date = new Date(d);
} catch (java.text.ParseException e) {
// ignore, use system date and go on
date = Time.currentTime();
}
s.skip("\\D*"); //$NON-NLS-1$
// drop
final List<BattleDrop> drop = new ArrayList<>(RxRessource.values().length);
for (int i = 0; i < RxRessource.values().length; ++i) {
final RxRessource res = RxRessource.values()[i];
if (!s.hasNextInt()) {
throw new ParseException(
MSG.bind(MSG.qreportParserResourceExpected, res));
}
final int amount = s.nextInt();
drop.add(new BattleDrop(res, amount));
}
s.nextLine();
final boolean artifact = s.hasNextInt() && s.nextInt() == 1;
if (artifact) {
s.nextLine();
}
if (!s.next().equals("Gefecht") || !s.next().equals("bei")) { //$NON-NLS-1$ //$NON-NLS-2$
throw new ParseException(MSG.qreportParserAttackAtExpected);
}
String quadrant = s.findInLine("\\D+"); //$NON-NLS-1$
if (quadrant == null) {
throw new ParseException(MSG.qreportParserInvalidLocation);
}
quadrant = quadrant.trim();
s.useDelimiter(",|\\s+"); //$NON-NLS-1$
final int x = s.nextInt();
final int y = s.nextInt();
s.useDelimiter(delimiter);
while (s.findInLine("Gefechtstaktik") == null) { //$NON-NLS-1$
s.nextLine();
}
final BattleTactic tactic = BattleTactic.parseTactic(s.nextLine().trim());
s.skip("\\s+Bonus Angreifer"); //$NON-NLS-1$
s.useDelimiter("%"); //$NON-NLS-1$
final double attackerBonus = 1.0 + (s.nextInt() / 100.0);
s.skip("%\\s+Bonus Verteidiger"); //$NON-NLS-1$
final double defenderBonus = 1.0 + (s.nextInt() / 100.0);
s.skip("%\\s+Kampfwert Angreifer/XP-Mod\\s*"); //$NON-NLS-1$
s.useDelimiter("/|\\s+"); //$NON-NLS-1$
final double kwAttacker = s.nextDouble();
final double xpModAttacker = s.nextDouble();
s.skip("\\s+Kampfwert Verteidiger/XP-Mod"); //$NON-NLS-1$
final double kwDefender = s.nextDouble();
final double xpModDefender = s.nextDouble();
// attacker fleet:
s.skip("\\s+Angreifer Flotte: "); //$NON-NLS-1$
s.useDelimiter(" \\("); //$NON-NLS-1$
final String attackerFleetName = s.next();
s.useDelimiter(" \\(|\\)"); //$NON-NLS-1$
String attackerName = s.next();
s.skip("\\)\\s*"); //$NON-NLS-1$
String attackerClan = ""; //$NON-NLS-1$
int i = attackerName.indexOf("["); //$NON-NLS-1$
if (i != -1) {
attackerClan = attackerName.substring(i + 1, attackerName.length() - 1);
attackerName = attackerName.substring(0, attackerName.length() - attackerClan.length() - 2);
}
final List<BattleReportShip> attackerShips = new ArrayList<>(50);
while (s.findInLine("Verteidiger Flotte: ") == null) { //$NON-NLS-1$
s.useDelimiter(delimiter);
final BattleReportShip ship = findShip(s);
attackerShips.add(ship);
}
// Defender fleet
s.useDelimiter(" \\("); //$NON-NLS-1$
final String defenderFleetName = s.next();
s.useDelimiter(" \\(|\\)"); //$NON-NLS-1$
String defenderName = s.next();
s.skip("\\)\\s*"); //$NON-NLS-1$
String defenderClan = ""; //$NON-NLS-1$
i = defenderName.indexOf("["); //$NON-NLS-1$
if (i != -1) {
defenderClan = defenderName.substring(i + 1, defenderName.length() - 1);
defenderName = defenderName.substring(0, defenderName.length() - defenderClan.length() - 2);
}
final List<BattleReportShip> defenderShips = new ArrayList<>(50);
s.useDelimiter(delimiter);
while (s.hasNext()) {
s.useDelimiter(delimiter);
final BattleReportShip ship = findShip(s);
defenderShips.add(ship);
}
final BattleReport br = new BattleReport(
submitterId,
quadrant,
x,
y,
drop,
artifact,
date,
tactic,
attackerBonus,
defenderBonus,
kwAttacker,
xpModAttacker,
kwDefender,
xpModDefender,
attackerFleetName,
attackerName,
defenderFleetName,
defenderName,
attackerClan,
defenderClan,
attackerShips,
defenderShips);
return br;
}
}
@SuppressWarnings("unused")
private static BattleReportShip findShip(Scanner s) throws ParseException {
s.skip("\\s*"); //$NON-NLS-1$
final String shipName = s.nextLine();
final String capiName = s.nextLine();
// find aw
final int currentAw = findAttribute1(s, "Angriffswert"); //$NON-NLS-1$
final int aw = findAttribute2(s);
final int awDmg = findDmg(s);
// capi hp/xp
final int currentHp = findAttribute1(s, "Captain"); //$NON-NLS-1$
final int hp = findAttribute2(s);
final int hpDmg = findDmg(s);
final int capiXp = findAttribute1(s, "XPs"); //$NON-NLS-1$
// shields
final int currentShield = findAttribute1(s, "Schild"); //$NON-NLS-1$
final int shield = findAttribute2(s);
final int shieldDmg = findDmg(s);
// crew
final int currentCrew = findAttribute1(s, "Crew"); //$NON-NLS-1$
final int crew = findAttribute2(s);
final int crewDmg = findDmg(s);
final int crewXp = findAttribute1(s, "XPs"); //$NON-NLS-1$
// pz
final int currentPz = findAttribute1(s, "Panzerung"); //$NON-NLS-1$
final int pz = findAttribute2(s);
final int pzDmg = findDmg(s);
// systems
final int currentSystem = findAttribute1(s, "Systeme"); //$NON-NLS-1$
final int system = findAttribute2(s);
final int systemDmg = findDmg(s);
// structure
final int currentStruct = findAttribute1(s, "Struktur"); //$NON-NLS-1$
final int struct = findAttribute2(s);
final int structDmg = findDmg(s);
int id = 0;
if (s.findInLine("ID:") != null) { //$NON-NLS-1$
s.useDelimiter("\\D+"); //$NON-NLS-1$
id = s.nextInt();
}
if (s.hasNextLine()) {
s.nextLine();
}
return new BattleReportShip(id,
shipName,
capiName,
aw,
shield,
pz,
struct,
currentCrew,
crew, system,
capiXp,
crewXp,
shieldDmg,
currentPz,
pzDmg,
structDmg,
systemDmg,
hp,
hpDmg,
awDmg,
crewDmg);
}
private static int findAttribute1(Scanner s, String skip) throws ParseException {
s.skip(Pattern.compile(".*?" + skip, Pattern.DOTALL)); //$NON-NLS-1$
if (!s.hasNextInt()) {
throw new ParseException(MSG.bind(MSG.qreportParserFailedToParseAttr, skip));
}
return s.nextInt();
}
private static int findAttribute2(Scanner s) {
s.skip(" / "); //$NON-NLS-1$
s.useDelimiter("\\D+"); //$NON-NLS-1$
return s.nextInt();
}
private static int findDmg(Scanner s) {
final String dmg = s.findInLine("\\(-\\d+\\)"); //$NON-NLS-1$
if (dmg != null) {
return Integer.parseInt(dmg.replaceAll("[()-]", "")); //$NON-NLS-1$ //$NON-NLS-2$
}
return 0;
}
}