/* Copyright (c) 2008-2010, developers of the Ascension Log Visualizer * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or * sell copies of the Software, and to permit persons to whom * the Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ package com.googlecode.logVisualizer.parser; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Scanner; import java.util.regex.Pattern; import com.googlecode.logVisualizer.Settings; import com.googlecode.logVisualizer.logData.LogDataHolder; import com.googlecode.logVisualizer.parser.MafiaSessionLogReader.LogBlock; import com.googlecode.logVisualizer.parser.MafiaSessionLogReader.LogBlockType; import com.googlecode.logVisualizer.parser.lineParsers.DayChangeLineParser; import com.googlecode.logVisualizer.parser.lineParsers.EquipmentLineParser; import com.googlecode.logVisualizer.parser.lineParsers.ItemAcquisitionLineParser; import com.googlecode.logVisualizer.parser.lineParsers.MPGainLineParser; import com.googlecode.logVisualizer.parser.lineParsers.MPGainLineParser.MPGainType; import com.googlecode.logVisualizer.parser.lineParsers.MafiaFamiliarChangeLineParser; import com.googlecode.logVisualizer.parser.lineParsers.MafiaPullLineParser; import com.googlecode.logVisualizer.parser.lineParsers.MeatLineParser; import com.googlecode.logVisualizer.parser.lineParsers.MeatLineParser.MeatGainType; import com.googlecode.logVisualizer.parser.lineParsers.MeatSpentLineParser; import com.googlecode.logVisualizer.parser.lineParsers.NotesLineParser; import com.googlecode.logVisualizer.parser.lineParsers.SkillCastLineParser; import com.googlecode.logVisualizer.parser.lineParsers.StatLineParser; import com.googlecode.logVisualizer.parser.mafiaLogBlockParsers.ConsumableBlockParser; import com.googlecode.logVisualizer.parser.mafiaLogBlockParsers.EncounterBlockParser; import com.googlecode.logVisualizer.parser.mafiaLogBlockParsers.PlayerSnapshotBlockParser; public final class MafiaLogParser implements LogParser { private static final Pattern THREE_FIGURE_STATGAIN = Pattern .compile("You gain \\d{3} [\\w\\s]+"); private static final String NAUGHTY_SORCERESS_FIGHT_STRING = "Sorceress Tower: Naughty Sorceress"; private final LogDataHolder logData = new LogDataHolder(); private final File log; private final EncounterBlockParser encounterParser = new EncounterBlockParser(); private final ConsumableBlockParser consumableParser = new ConsumableBlockParser(); private final PlayerSnapshotBlockParser playerSnapshotParser = new PlayerSnapshotBlockParser(); private final List<LineParser> lineParsers = new ArrayList<>(); /** * @param log * The mafia ascension log which is intended to be parsed to set. * @throws NullPointerException * if log is {@code null} */ public MafiaLogParser(final File log, final boolean isIncludeMafiaLogNotes) { this.log = log; // Set the log name this.getLogData().setLogName( log.getName().replace(".txt", UsefulPatterns.EMPTY_STRING)); this.lineParsers.add(new ItemAcquisitionLineParser()); this.lineParsers.add(new SkillCastLineParser()); this.lineParsers.add(new MafiaFamiliarChangeLineParser()); this.lineParsers.add(new MeatLineParser(MeatGainType.OTHER)); this.lineParsers.add(new MeatSpentLineParser()); this.lineParsers.add(new StatLineParser()); this.lineParsers.add(new MPGainLineParser(MPGainType.NOT_ENCOUNTER)); this.lineParsers.add(new EquipmentLineParser()); this.lineParsers.add(new MafiaPullLineParser()); this.lineParsers.add(new DayChangeLineParser()); if (isIncludeMafiaLogNotes) { this.lineParsers.add(new NotesLineParser()); } } /** * {@inheritDoc} */ @Override public void parse() throws IOException { final MafiaSessionLogReader reader = new MafiaSessionLogReader(this.log); final boolean isOldAscensionCounting = Settings .getSettingBoolean("Using old ascension counting"); boolean nsFightWon = false; while (reader.hasNext() && !nsFightWon) { final LogBlock block = reader.next(); // In case old ascension turn counting is turned off and the current // block is an encounter block, we need to check whether the Naughty // Sorceress was beaten in it. if (!isOldAscensionCounting && (block.getBlockType() == LogBlockType.ENCOUNTER_BLOCK)) { final String tmp = block.getBlockLines().get(0); if (tmp.endsWith(MafiaLogParser.NAUGHTY_SORCERESS_FIGHT_STRING)) { nsFightWon = MafiaLogParser.isNaughtySorceressBeaten(block); } } // Now, we do the actual parsing. switch (block.getBlockType()) { case ENCOUNTER_BLOCK: this.encounterParser.parseBlock(block.getBlockLines(), this.logData); break; case CONSUMABLE_BLOCK: this.consumableParser.parseBlock(block.getBlockLines(), this.logData); break; case PLAYER_SNAPSHOT_BLOCK: this.playerSnapshotParser.parseBlock(block.getBlockLines(), this.logData); break; case OTHER_BLOCK: for (final String line : block.getBlockLines()) { for (final LineParser lp : this.lineParsers) { // If the line parser can parse the line, this // method also returns true. This is used to cut // back on the amount of loops. if (lp.parseLine(line, this.logData)) { break; } } } break; default: break; } } reader.close(); this.getLogData().createLogSummary(); } /** * This method checks whether the Naughty Sorceress has been beaten. * * @param block * The Naughty Sorceress encounter block. * @return True if the Naughty Sorceress was beaten, otherwise false. */ private static boolean isNaughtySorceressBeaten(final LogBlock block) { for (final String line : block.getBlockLines()) { // Three figure stat gains aren't possible through combat items // while winning against the NS will give these amounts, so if there // is such a line, it means the fight has been won. if (MafiaLogParser.THREE_FIGURE_STATGAIN.matcher(line).matches()) { try (final Scanner scanner = new Scanner(line)) { scanner.findInLine(UsefulPatterns.GAIN_LOSE_CAPTURE_PATTERN); final String substatName = scanner.match().group(2); scanner.close(); if (UsefulPatterns.MUSCLE_SUBSTAT_NAMES .contains(substatName) || UsefulPatterns.MYST_SUBSTAT_NAMES .contains(substatName) || UsefulPatterns.MOXIE_SUBSTAT_NAMES .contains(substatName)) { return true; } } } } return false; } /** * {@inheritDoc} */ @Override public LogDataHolder getLogData() { return this.logData; } /** * {@inheritDoc} */ @Override public boolean isDetailedLogData() { return true; } }