package polly.rx.parsing; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.EnumMap; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Scanner; import java.util.regex.Pattern; import polly.rx.MSG; import polly.rx.core.orion.Orion; import polly.rx.core.orion.model.DefaultBattleReport; import polly.rx.core.orion.model.DefaultBattleReportCompetitor; import polly.rx.core.orion.model.DefaultDrop; import polly.rx.core.orion.model.DefaultReportShip; import polly.rx.core.orion.model.DefaultSector; import polly.rx.core.orion.model.DefaultShipStats; import polly.rx.core.orion.model.Quadrant; import polly.rx.core.orion.model.ReportShip; import polly.rx.entities.BattleTactic; import polly.rx.entities.RxRessource; import polly.rx.entities.ShipHelper; import polly.rx.entities.ShipType; import de.skuzzle.polly.sdk.time.Milliseconds; import de.skuzzle.polly.sdk.time.Time; public class NewModelReportParser { private final static DateFormat getDateFormat() { return new SimpleDateFormat("HH:mm dd-MM-yyyy"); //$NON-NLS-1$ } public static DefaultBattleReport parse(String report) 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 Map<RxRessource, Integer> d = new EnumMap<>(RxRessource.class); 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(); d.put(res, amount); } s.nextLine(); final boolean artifact = s.hasNextInt() && s.nextInt() == 1; if (artifact) { s.nextLine(); } final DefaultDrop drop = new DefaultDrop(d, artifact); 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 float attackerBonus = 1.0f + (s.nextInt() / 100.0f); s.skip("%\\s+Bonus Verteidiger"); //$NON-NLS-1$ final float defenderBonus = 1.0f + (s.nextInt() / 100.0f); s.skip("%\\s+Kampfwert Angreifer/XP-Mod\\s*"); //$NON-NLS-1$ s.useDelimiter("/|\\s+"); //$NON-NLS-1$ final float kwAttacker = s.nextFloat() / attackerBonus; final float xpModAttacker = s.nextFloat(); s.skip("\\s+Kampfwert Verteidiger/XP-Mod"); //$NON-NLS-1$ final float kwDefender = s.nextFloat() / defenderBonus; final float xpModDefender = s.nextFloat(); // 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$ final String attackerClan = VenadHelper.getClan(attackerName); attackerName = VenadHelper.getName(attackerName); final List<ReportShip> attackerShips = new ArrayList<>(50); while (s.findInLine("Verteidiger Flotte: ") == null) { //$NON-NLS-1$ s.useDelimiter(delimiter); final DefaultReportShip ship = findShip(s, date); 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$ final String defenderClan = VenadHelper.getClan(defenderName); defenderName = VenadHelper.getName(defenderName); final List<ReportShip> defenderShips = new ArrayList<>(50); s.useDelimiter(delimiter); while (s.hasNext()) { s.useDelimiter(delimiter); final DefaultReportShip ship = findShip(s, date); defenderShips.add(ship); } final DefaultBattleReportCompetitor attacker = new DefaultBattleReportCompetitor(attackerName, attackerClan, attackerFleetName, kwAttacker, xpModAttacker, attackerShips); final DefaultBattleReportCompetitor defender = new DefaultBattleReportCompetitor(defenderName, defenderClan, defenderFleetName, kwDefender, xpModDefender, defenderShips); final Quadrant q = Orion.INSTANCE.getQuadrantProvider().getQuadrant(quadrant); final DefaultSector location = new DefaultSector(q.getSector(x, y)); final DefaultBattleReport result = new DefaultBattleReport(tactic, attacker, defender, location, drop, date); return result; } } @SuppressWarnings("unused") private static DefaultReportShip findShip(Scanner s, Date date) 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(); } final DefaultShipStats stats = new DefaultShipStats(aw, shield, pz, struct, currentCrew, crew); final DefaultShipStats dmg = new DefaultShipStats(awDmg, shieldDmg, pzDmg, structDmg, crewDmg, crewDmg); final ShipType type = ShipHelper.getShipType(shipName); final int shipClass = ShipHelper.getShipClass(shipName); final String simpleName = ShipHelper.getSimpleName(shipName); return new DefaultReportShip(type, simpleName, capiName, stats, dmg, shipClass, id, crewXp, capiXp, date); } 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; } }