use of games.strategy.engine.history.Round in project triplea by triplea-game.
the class ScreenshotExporter method save.
private void save(final GameData gameData, final HistoryNode node, final File file) throws IOException {
// get round/step/player from history tree
int round = 0;
final Object[] pathFromRoot = node.getPath();
for (final Object pathNode : pathFromRoot) {
final HistoryNode curNode = (HistoryNode) pathNode;
if (curNode instanceof Round) {
round = ((Round) curNode).getRoundNo();
}
}
final UiContext uiContext = frame.getUiContext();
final double scale = uiContext.getScale();
// print map panel to image
final MapPanel mapPanel = frame.getMapPanel();
final BufferedImage mapImage = Util.createImage((int) (scale * mapPanel.getImageWidth()), (int) (scale * mapPanel.getImageHeight()), false);
final Graphics2D mapGraphics = mapImage.createGraphics();
try {
// workaround to get the whole map
// (otherwise the map is cut if current window is not on top of map)
final int offsetX = mapPanel.getXOffset();
final int offsetY = mapPanel.getYOffset();
mapPanel.setTopLeft(0, 0);
mapPanel.drawMapImage(mapGraphics);
mapPanel.setTopLeft(offsetX, offsetY);
// overlay title
Color titleColor = uiContext.getMapData().getColorProperty(MapData.PROPERTY_SCREENSHOT_TITLE_COLOR);
if (titleColor == null) {
titleColor = Color.BLACK;
}
final String encodedTitleX = uiContext.getMapData().getProperty(MapData.PROPERTY_SCREENSHOT_TITLE_X);
final String encodedTitleY = uiContext.getMapData().getProperty(MapData.PROPERTY_SCREENSHOT_TITLE_Y);
final String encodedTitleSize = uiContext.getMapData().getProperty(MapData.PROPERTY_SCREENSHOT_TITLE_FONT_SIZE);
int titleX;
int titleY;
int titleSize;
try {
titleX = (int) (Integer.parseInt(encodedTitleX) * scale);
titleY = (int) (Integer.parseInt(encodedTitleY) * scale);
titleSize = Integer.parseInt(encodedTitleSize);
} catch (final NumberFormatException nfe) {
// choose safe defaults
titleX = (int) (15 * scale);
titleY = (int) (15 * scale);
titleSize = 15;
}
// everything else should be scaled down onto map image
final AffineTransform transform = new AffineTransform();
transform.scale(scale, scale);
mapGraphics.setTransform(transform);
mapGraphics.setFont(new Font("Ariel", Font.BOLD, titleSize));
mapGraphics.setColor(titleColor);
if (uiContext.getMapData().getBooleanProperty(MapData.PROPERTY_SCREENSHOT_TITLE_ENABLED)) {
mapGraphics.drawString(gameData.getGameName() + " Round " + round, titleX, titleY);
}
// save Image as .png
ImageIO.write(mapImage, "png", file);
} finally {
// Clean up objects. There might be some overkill here,
// but there were memory leaks that are fixed by some/all of these.
mapImage.flush();
mapGraphics.dispose();
}
}
use of games.strategy.engine.history.Round in project triplea by triplea-game.
the class ExportMenu method createAndSaveStats.
private void createAndSaveStats(final boolean showPhaseStats) {
final ExtendedStats statPanel = new ExtendedStats(gameData, uiContext);
final JFileChooser chooser = new JFileChooser();
chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
final File rootDir = new File(SystemProperties.getUserDir());
final int currentRound = gameData.getCurrentRound();
String defaultFileName = "stats_" + dateTimeFormatter.format(LocalDateTime.now()) + "_" + gameData.getGameName() + "_round_" + currentRound + (showPhaseStats ? "_full" : "_short");
defaultFileName = FileNameUtils.removeIllegalCharacters(defaultFileName);
defaultFileName = defaultFileName + ".csv";
chooser.setSelectedFile(new File(rootDir, defaultFileName));
if (chooser.showSaveDialog(frame) != JOptionPane.OK_OPTION) {
return;
}
final StringBuilder text = new StringBuilder(1000);
try {
gameData.acquireReadLock();
final GameData clone = GameDataUtils.cloneGameData(gameData);
final IStat[] stats = statPanel.getStats();
// extended stats covers stuff that doesn't show up in the game stats menu bar, like custom resources or tech
// tokens or # techs, etc.
final IStat[] statsExtended = statPanel.getStatsExtended(gameData);
final String[] alliances = statPanel.getAlliances().toArray(new String[0]);
final PlayerID[] players = statPanel.getPlayers().toArray(new PlayerID[0]);
// its important here to translate the player objects into our game data
// the players for the stat panel are only relevant with respect to
// the game data they belong to
Arrays.setAll(players, i -> clone.getPlayerList().getPlayerId(players[i].getName()));
text.append(defaultFileName).append(",");
text.append("\n");
text.append("TripleA Engine Version: ,");
text.append(ClientContext.engineVersion()).append(",");
text.append("\n");
text.append("Game Name: ,");
text.append(gameData.getGameName()).append(",");
text.append("\n");
text.append("Game Version: ,");
text.append(gameData.getGameVersion()).append(",");
text.append("\n");
text.append("\n");
text.append("Current Round: ,");
text.append(currentRound).append(",");
text.append("\n");
text.append("Number of Players: ,");
text.append(statPanel.getPlayers().size()).append(",");
text.append("\n");
text.append("Number of Alliances: ,");
text.append(statPanel.getAlliances().size()).append(",");
text.append("\n");
text.append("\n");
text.append("Turn Order: ,");
text.append("\n");
final List<PlayerID> playerOrderList = new ArrayList<>(gameData.getPlayerList().getPlayers());
playerOrderList.sort(new PlayerOrderComparator(gameData));
final Set<PlayerID> playerOrderSetNoDuplicates = new LinkedHashSet<>(playerOrderList);
for (final PlayerID currentPlayerId : playerOrderSetNoDuplicates) {
text.append(currentPlayerId.getName()).append(",");
final Collection<String> allianceNames = gameData.getAllianceTracker().getAlliancesPlayerIsIn(currentPlayerId);
for (final String allianceName : allianceNames) {
text.append(allianceName).append(",");
}
text.append("\n");
}
text.append("\n");
text.append("Winners: ,");
final EndRoundDelegate delegateEndRound = (EndRoundDelegate) gameData.getDelegateList().getDelegate("endRound");
if (delegateEndRound != null && delegateEndRound.getWinners() != null) {
for (final PlayerID p : delegateEndRound.getWinners()) {
text.append(p.getName()).append(",");
}
} else {
text.append("none yet; game not over,");
}
text.append("\n");
text.append("\n");
text.append("Resource Chart: ,");
text.append("\n");
for (final Resource resource : gameData.getResourceList().getResources()) {
text.append(resource.getName()).append(",");
text.append("\n");
}
// if short, we won't both showing production and unit info
if (showPhaseStats) {
text.append("\n");
text.append("Production Rules: ,");
text.append("\n");
text.append("Name,Result,Quantity,Cost,Resource,\n");
final Collection<ProductionRule> purchaseOptions = gameData.getProductionRuleList().getProductionRules();
for (final ProductionRule pr : purchaseOptions) {
String costString = pr.toStringCosts().replaceAll("; ", ",");
costString = costString.replaceAll(" ", ",");
text.append(pr.getName()).append(",").append(pr.getResults().keySet().iterator().next().getName()).append(",").append(pr.getResults().getInt(pr.getResults().keySet().iterator().next())).append(",").append(costString).append(",");
text.append("\n");
}
text.append("\n");
text.append("Unit Types: ,");
text.append("\n");
text.append("Name,Listed Abilities\n");
for (final UnitType unitType : gameData.getUnitTypeList()) {
final UnitAttachment ua = UnitAttachment.get(unitType);
if (ua == null) {
continue;
}
String toModify = ua.allUnitStatsForExporter();
toModify = toModify.replaceFirst("UnitType called ", "").replaceFirst(" with:", "").replaceAll("games.strategy.engine.data.", "").replaceAll("\n", ";").replaceAll(",", ";");
toModify = toModify.replaceAll(" ", ",");
toModify = toModify.replaceAll(", ", ",").replaceAll(" ,", ",");
text.append(toModify);
text.append("\n");
}
}
text.append("\n");
text.append((showPhaseStats ? "Full Stats (includes each phase that had activity)," : "Short Stats (only shows first phase with activity per player per round),"));
text.append("\n");
text.append("Turn Stats: ,");
text.append("\n");
text.append("Round,Player Turn,Phase Name,");
for (final IStat stat : stats) {
for (final PlayerID player : players) {
text.append(stat.getName()).append(" ");
text.append(player.getName());
text.append(",");
}
for (final String alliance : alliances) {
text.append(stat.getName()).append(" ");
text.append(alliance);
text.append(",");
}
}
for (final IStat element : statsExtended) {
for (final PlayerID player : players) {
text.append(element.getName()).append(" ");
text.append(player.getName());
text.append(",");
}
for (final String alliance : alliances) {
text.append(element.getName()).append(" ");
text.append(alliance);
text.append(",");
}
}
text.append("\n");
clone.getHistory().gotoNode(clone.getHistory().getLastNode());
@SuppressWarnings("unchecked") final Enumeration<TreeNode> nodes = ((DefaultMutableTreeNode) clone.getHistory().getRoot()).preorderEnumeration();
PlayerID currentPlayer = null;
int round = 0;
while (nodes.hasMoreElements()) {
// we want to export on change of turn
final HistoryNode element = (HistoryNode) nodes.nextElement();
if (element instanceof Round) {
round++;
}
if (!(element instanceof Step)) {
continue;
}
final Step step = (Step) element;
if (step.getPlayerId() == null || step.getPlayerId().isNull()) {
continue;
}
// this is to stop from having multiple entries for each players turn.
if (!showPhaseStats) {
if (step.getPlayerId() == currentPlayer) {
continue;
}
}
currentPlayer = step.getPlayerId();
clone.getHistory().gotoNode(element);
final String playerName = step.getPlayerId() == null ? "" : step.getPlayerId().getName() + ": ";
String stepName = step.getStepName();
// copied directly from TripleAPlayer, will probably have to be updated in the future if more delegates are made
if (stepName.endsWith("Bid")) {
stepName = "Bid";
} else if (stepName.endsWith("Tech")) {
stepName = "Tech";
} else if (stepName.endsWith("TechActivation")) {
stepName = "TechActivation";
} else if (stepName.endsWith("Purchase")) {
stepName = "Purchase";
} else if (stepName.endsWith("NonCombatMove")) {
stepName = "NonCombatMove";
} else if (stepName.endsWith("Move")) {
stepName = "Move";
} else if (stepName.endsWith("Battle")) {
stepName = "Battle";
} else if (stepName.endsWith("BidPlace")) {
stepName = "BidPlace";
} else if (stepName.endsWith("Place")) {
stepName = "Place";
} else if (stepName.endsWith("Politics")) {
stepName = "Politics";
} else if (stepName.endsWith("EndTurn")) {
stepName = "EndTurn";
} else {
stepName = "";
}
text.append(round).append(",").append(playerName).append(",").append(stepName).append(",");
for (final IStat stat : stats) {
for (final PlayerID player : players) {
text.append(stat.getFormatter().format(stat.getValue(player, clone)));
text.append(",");
}
for (final String alliance : alliances) {
text.append(stat.getFormatter().format(stat.getValue(alliance, clone)));
text.append(",");
}
}
for (final IStat element2 : statsExtended) {
for (final PlayerID player : players) {
text.append(element2.getFormatter().format(element2.getValue(player, clone)));
text.append(",");
}
for (final String alliance : alliances) {
text.append(element2.getFormatter().format(element2.getValue(alliance, clone)));
text.append(",");
}
}
text.append("\n");
}
} finally {
gameData.releaseReadLock();
}
try (Writer writer = Files.newBufferedWriter(chooser.getSelectedFile().toPath(), StandardCharsets.UTF_8)) {
writer.write(text.toString());
} catch (final IOException e1) {
ClientLogger.logQuietly("Failed to write stats: " + chooser.getSelectedFile().getAbsolutePath(), e1);
}
}
use of games.strategy.engine.history.Round in project triplea by triplea-game.
the class CommentPanel method loadHistory.
private void loadHistory() {
final Document doc = text.getDocument();
final HistoryNode rootNode = (HistoryNode) data.getHistory().getRoot();
@SuppressWarnings("unchecked") final Enumeration<TreeNode> nodeEnum = rootNode.preorderEnumeration();
final Pattern p = Pattern.compile("^COMMENT: (.*)");
String player = "";
int round = 0;
Icon icon = null;
while (nodeEnum.hasMoreElements()) {
final HistoryNode node = (HistoryNode) nodeEnum.nextElement();
if (node instanceof Round) {
round++;
} else if (node instanceof Step) {
final PlayerID playerId = ((Step) node).getPlayerId();
if (playerId != null) {
player = playerId.getName();
icon = iconMap.get(playerId);
}
} else {
final String title = node.getTitle();
final Matcher m = p.matcher(title);
if (m.matches()) {
try {
// insert into ui document
final String prefix = " " + player + "(" + round + ") : ";
text.insertIcon(icon);
doc.insertString(doc.getLength(), prefix, bold);
doc.insertString(doc.getLength(), m.group(1) + "\n", normal);
} catch (final BadLocationException e) {
ClientLogger.logQuietly("Failed to add history", e);
}
}
}
}
}
use of games.strategy.engine.history.Round in project triplea by triplea-game.
the class TripleAFrame method showHistory.
private void showHistory() {
inHistory = true;
inGame = false;
setWidgetActivation();
final GameData clonedGameData;
data.acquireReadLock();
try {
// we want to use a clone of the data, so we can make changes to it
// as we walk up and down the history
clonedGameData = GameDataUtils.cloneGameData(data);
if (clonedGameData == null) {
return;
}
data.removeDataChangeListener(dataChangeListener);
clonedGameData.testLocksOnRead();
if (historySyncher != null) {
throw new IllegalStateException("Two history synchers?");
}
historySyncher = new HistorySynchronizer(clonedGameData, game);
clonedGameData.addDataChangeListener(dataChangeListener);
} finally {
data.releaseReadLock();
}
statsPanel.setGameData(clonedGameData);
economyPanel.setGameData(clonedGameData);
if (objectivePanel != null && !objectivePanel.isEmpty()) {
objectivePanel.setGameData(clonedGameData);
}
details.setGameData(clonedGameData);
mapPanel.setGameData(clonedGameData);
final HistoryDetailsPanel historyDetailPanel = new HistoryDetailsPanel(clonedGameData, mapPanel);
tabsPanel.removeAll();
tabsPanel.add("History", historyDetailPanel);
addTab("Players", statsPanel, 'P');
addTab("Resources", economyPanel, 'R');
if (objectivePanel != null && !objectivePanel.isEmpty()) {
addTab(objectivePanel.getName(), objectivePanel, 'O');
}
addTab("Notes", notesPanel, 'N');
addTab("Territory", details, 'T');
if (getEditMode()) {
tabsPanel.add("Edit", editPanel);
}
if (actionButtons.getCurrent() != null) {
actionButtons.getCurrent().setActive(false);
}
historyComponent.removeAll();
historyComponent.setLayout(new BorderLayout());
// create history tree context menu
// actions need to clear the history panel popup state when done
final JPopupMenu popup = new JPopupMenu();
popup.add(new AbstractAction("Show Summary Log") {
private static final long serialVersionUID = -6730966512179268157L;
@Override
public void actionPerformed(final ActionEvent ae) {
final HistoryLog historyLog = new HistoryLog();
historyLog.printRemainingTurn(historyPanel.getCurrentPopupNode(), false, data.getDiceSides(), null);
historyLog.printTerritorySummary(historyPanel.getCurrentPopupNode(), clonedGameData);
historyLog.printProductionSummary(clonedGameData);
historyPanel.clearCurrentPopupNode();
historyLog.setVisible(true);
}
});
popup.add(new AbstractAction("Show Detailed Log") {
private static final long serialVersionUID = -8709762764495294671L;
@Override
public void actionPerformed(final ActionEvent ae) {
final HistoryLog historyLog = new HistoryLog();
historyLog.printRemainingTurn(historyPanel.getCurrentPopupNode(), true, data.getDiceSides(), null);
historyLog.printTerritorySummary(historyPanel.getCurrentPopupNode(), clonedGameData);
historyLog.printProductionSummary(clonedGameData);
historyPanel.clearCurrentPopupNode();
historyLog.setVisible(true);
}
});
popup.add(new AbstractAction("Export Map Snapshot") {
private static final long serialVersionUID = 1222760138263428443L;
@Override
public void actionPerformed(final ActionEvent ae) {
ScreenshotExporter.exportScreenshot(TripleAFrame.this, data, historyPanel.getCurrentPopupNode());
historyPanel.clearCurrentPopupNode();
}
});
popup.add(new AbstractAction("Save Game at this point (BETA)") {
private static final long serialVersionUID = 1430512376199927896L;
@Override
public void actionPerformed(final ActionEvent ae) {
JOptionPane.showMessageDialog(TripleAFrame.this, "Please first left click on the spot you want to save from, Then right click and select 'Save Game From " + "History'" + "\n\nIt is recommended that when saving the game from the History panel:" + "\n * Your CURRENT GAME is at the start of some player's turn, and that no moves have been made and " + "no actions taken yet." + "\n * The point in HISTORY that you are trying to save at, is at the beginning of a player's turn, " + "or the beginning of a round." + "\nSaving at any other point, could potentially create errors." + "\nFor example, saving while your current game is in the middle of a move or battle phase will " + "always create errors in the savegame." + "\nAnd you will also get errors in the savegame if you try to create a save at a point in history " + "such as a move or battle phase.", "Save Game from History", JOptionPane.INFORMATION_MESSAGE);
data.acquireReadLock();
try {
final File f = TripleAMenuBar.getSaveGameLocation(TripleAFrame.this);
if (f != null) {
try (FileOutputStream fout = new FileOutputStream(f)) {
final GameData datacopy = GameDataUtils.cloneGameData(data, true);
datacopy.getHistory().gotoNode(historyPanel.getCurrentPopupNode());
datacopy.getHistory().removeAllHistoryAfterNode(historyPanel.getCurrentPopupNode());
// TODO: the saved current delegate is still the current delegate,
// rather than the delegate at that history popup node
// TODO: it still shows the current round number, rather than the round at the history popup node
// TODO: this could be solved easily if rounds/steps were changes,
// but that could greatly increase the file size :(
// TODO: this also does not undo the runcount of each delegate step
@SuppressWarnings("unchecked") final Enumeration<TreeNode> enumeration = ((DefaultMutableTreeNode) datacopy.getHistory().getRoot()).preorderEnumeration();
enumeration.nextElement();
int round = 0;
String stepDisplayName = datacopy.getSequence().getStep(0).getDisplayName();
PlayerID currentPlayer = datacopy.getSequence().getStep(0).getPlayerId();
while (enumeration.hasMoreElements()) {
final HistoryNode node = (HistoryNode) enumeration.nextElement();
if (node instanceof Round) {
round = Math.max(0, ((Round) node).getRoundNo() - datacopy.getSequence().getRoundOffset());
currentPlayer = null;
stepDisplayName = node.getTitle();
} else if (node instanceof Step) {
currentPlayer = ((Step) node).getPlayerId();
stepDisplayName = node.getTitle();
}
}
datacopy.getSequence().setRoundAndStep(round, stepDisplayName, currentPlayer);
GameDataManager.saveGame(fout, datacopy);
JOptionPane.showMessageDialog(TripleAFrame.this, "Game Saved", "Game Saved", JOptionPane.INFORMATION_MESSAGE);
} catch (final IOException e) {
ClientLogger.logQuietly("Failed to save game: " + f.getAbsolutePath(), e);
}
}
} finally {
data.releaseReadLock();
}
historyPanel.clearCurrentPopupNode();
}
});
final JSplitPane split = new JSplitPane();
split.setOneTouchExpandable(true);
split.setDividerSize(8);
historyPanel = new HistoryPanel(clonedGameData, historyDetailPanel, popup, uiContext);
split.setLeftComponent(historyPanel);
split.setRightComponent(gameCenterPanel);
split.setDividerLocation(150);
historyComponent.add(split, BorderLayout.CENTER);
historyComponent.add(gameSouthPanel, BorderLayout.SOUTH);
getContentPane().removeAll();
getContentPane().add(historyComponent, BorderLayout.CENTER);
validate();
}
use of games.strategy.engine.history.Round in project triplea by triplea-game.
the class HistoryLog method printRemainingTurn.
public void printRemainingTurn(final HistoryNode printNode, final boolean verbose, final int diceSides, final Collection<PlayerID> playersAllowed) {
final PrintWriter logWriter = printWriter;
final String moreIndent = " ";
// print out the parent nodes
final TreePath parentPath = (new TreePath(printNode.getPath())).getParentPath();
PlayerID currentPlayer = null;
if (parentPath != null) {
final Object[] pathToNode = parentPath.getPath();
for (final Object pathNode : pathToNode) {
final HistoryNode node = (HistoryNode) pathNode;
for (int i = 0; i < node.getLevel(); i++) {
logWriter.print(moreIndent);
}
logWriter.println(node.getTitle());
if (node.getLevel() == 0) {
logWriter.println();
}
if (node instanceof Step) {
currentPlayer = ((Step) node).getPlayerId();
}
}
}
final Collection<PlayerID> players = new HashSet<>();
if (playersAllowed != null) {
players.addAll(playersAllowed);
}
if (currentPlayer != null) {
players.add(currentPlayer);
}
final List<String> moveList = new ArrayList<>();
boolean moving = false;
DefaultMutableTreeNode curNode = printNode;
final Map<String, Double> hitDifferentialMap = new HashMap<>();
do {
// keep track of conquered territory during combat
StringBuilder conquerStr = new StringBuilder();
final Enumeration<?> nodeEnum = curNode.preorderEnumeration();
while (nodeEnum.hasMoreElements()) {
final HistoryNode node = (HistoryNode) nodeEnum.nextElement();
final String title = node.getTitle();
final StringBuilder indent = new StringBuilder();
for (int i = 0; i < node.getLevel(); i++) {
indent.append(moreIndent);
}
// flush move list
if (moving && !(node instanceof Renderable)) {
final Iterator<String> moveIter = moveList.iterator();
while (moveIter.hasNext()) {
logWriter.println(moveIter.next());
moveIter.remove();
}
moving = false;
}
if (node instanceof Renderable) {
final Object details = ((Renderable) node).getRenderingData();
if (details instanceof DiceRoll) {
if (!verbose) {
continue;
}
final String diceMsg1 = title.substring(0, title.indexOf(':') + 1);
if (diceMsg1.isEmpty()) {
// tech roll
logWriter.println(indent + moreIndent + title);
} else {
// dice roll
// Japanese roll dice for 1 armour in Russia, round 1
logWriter.print(indent + moreIndent + diceMsg1);
final String player = diceMsg1.split(" roll ")[0];
final DiceRoll diceRoll = (DiceRoll) details;
final int hits = diceRoll.getHits();
int rolls = 0;
for (int i = 1; i <= diceSides; i++) {
rolls += diceRoll.getRolls(i).size();
}
final double expectedHits = diceRoll.getExpectedHits();
logWriter.println(" " + hits + "/" + rolls + " hits, " + String.format("%.2f", expectedHits) + " expected hits");
final double hitDifferential = hits - expectedHits;
if (hitDifferentialMap.containsKey(player)) {
hitDifferentialMap.put(player, hitDifferentialMap.get(player) + hitDifferential);
} else {
hitDifferentialMap.put(player, hitDifferential);
}
}
} else if (details instanceof MoveDescription) {
// movement
final Pattern p = Pattern.compile("\\w+ undo move (\\d+).");
final Matcher m = p.matcher(title);
if (m.matches()) {
moveList.remove(Integer.valueOf(m.group(1)) - 1);
} else {
moveList.add(indent + title);
moving = true;
}
} else if (details instanceof Collection) {
@SuppressWarnings("unchecked") final Collection<Object> objects = (Collection<Object>) details;
final Iterator<Object> objIter = objects.iterator();
if (objIter.hasNext()) {
final Object obj = objIter.next();
if (obj instanceof Unit) {
@SuppressWarnings("unchecked") final Collection<Unit> allUnitsInDetails = (Collection<Unit>) details;
// purchase/place units - don't need details
Unit unit = (Unit) obj;
if (title.matches("\\w+ buy .*") || title.matches("\\w+ attack with .*") || title.matches("\\w+ defend with .*")) {
logWriter.println(indent + title);
} else if (title.matches("\\d+ \\w+ owned by the .*? lost .*") || title.matches("\\d+ \\w+ owned by the .*? lost")) {
if (!verbose) {
continue;
}
logWriter.println(indent + moreIndent + title);
} else if (title.startsWith("Battle casualty summary:")) {
// logWriter.println(indent+"CAS1: "+title);
logWriter.println(indent + conquerStr.toString() + ". Battle score " + title.substring(title.indexOf("for attacker is")));
conquerStr = new StringBuilder();
// separate units by player and show casualty summary
final IntegerMap<PlayerID> unitCount = new IntegerMap<>();
unitCount.add(unit.getOwner(), 1);
while (objIter.hasNext()) {
unit = (Unit) objIter.next();
unitCount.add(unit.getOwner(), 1);
}
for (final PlayerID player : unitCount.keySet()) {
logWriter.println(indent + "Casualties for " + player.getName() + ": " + MyFormatter.unitsToTextNoOwner(allUnitsInDetails, player));
}
} else if (title.matches(".*? placed in .*") || title.matches(".* owned by the \\w+ retreated to .*")) {
logWriter.println(indent + title);
} else if (title.matches("\\w+ win")) {
conquerStr = new StringBuilder(title + conquerStr + " with " + MyFormatter.unitsToTextNoOwner(allUnitsInDetails) + " remaining");
} else {
logWriter.println(indent + title);
}
} else {
// collection of unhandled objects
logWriter.println(indent + title);
}
} else {
// empty collection of something
if (title.matches("\\w+ win")) {
conquerStr = new StringBuilder(title + conquerStr + " with no units remaining");
} else {
// empty collection of unhandled objects
logWriter.println(indent + title);
}
}
} else if (details instanceof Territory) {
// territory details
logWriter.println(indent + title);
} else if (details == null) {
if (title.equals("Adding original owners") || title.equals(MoveDelegate.CLEANING_UP_DURING_MOVEMENT_PHASE) || title.equals("Game Loaded") || title.contains("now being played by") || title.contains("Turn Summary") || title.contains("Move Summary") || title.contains("Setting uses for triggers used") || title.equals("Resetting and Giving Bonus Movement to Units") || title.equals("Recording Battle Statistics") || title.equals("Preparing Airbases for Possible Scrambling")) {
// do nothing
} else if (title.matches("\\w+ collect \\d+ PUs?.*")) {
logWriter.println(indent + title);
} else if (title.matches("\\w+ takes? .*? from \\w+")) {
// British take Libya from Germans
if (moving) {
final String str = moveList.remove(moveList.size() - 1);
moveList.add(str + "\n " + indent + title.replaceAll(" takes ", " take "));
} else {
conquerStr.append(title.replaceAll("^\\w+ takes ", ", taking "));
}
} else if (title.matches("\\w+ spend \\d+ on tech rolls")) {
logWriter.println(indent + title);
} else if (title.startsWith("Rolls to resolve tech hits:")) {
// do nothing
} else {
logWriter.println(indent + title);
}
} else {
// unknown details object
logWriter.println(indent + title);
}
} else if (node instanceof Step) {
final PlayerID playerId = ((Step) node).getPlayerId();
if (!title.equals("Initializing Delegates")) {
logWriter.println();
logWriter.print(indent + title);
if (playerId != null) {
currentPlayer = playerId;
players.add(currentPlayer);
logWriter.print(" - " + playerId.getName());
}
logWriter.println();
}
} else if (node instanceof Round) {
logWriter.println();
logWriter.println(indent + title);
} else {
logWriter.println(indent + title);
}
}
// while (nodeEnum.hasMoreElements())
curNode = curNode.getNextSibling();
} while ((curNode instanceof Step) && players.contains(((Step) curNode).getPlayerId()));
// if we are mid-phase, this might not get flushed
if (moving && !moveList.isEmpty()) {
final Iterator<String> moveIter = moveList.iterator();
while (moveIter.hasNext()) {
logWriter.println(moveIter.next());
moveIter.remove();
}
}
logWriter.println();
if (verbose) {
logWriter.println("Combat Hit Differential Summary :");
logWriter.println();
for (final String player : hitDifferentialMap.keySet()) {
logWriter.println(moreIndent + player + " : " + String.format("%.2f", hitDifferentialMap.get(player)));
}
}
logWriter.println();
textArea.setText(stringWriter.toString());
}
Aggregations