Search in sources :

Example 1 with Round

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();
    }
}
Also used : MapPanel(games.strategy.triplea.ui.MapPanel) Color(java.awt.Color) BufferedImage(java.awt.image.BufferedImage) Font(java.awt.Font) Graphics2D(java.awt.Graphics2D) HistoryNode(games.strategy.engine.history.HistoryNode) Round(games.strategy.engine.history.Round) AffineTransform(java.awt.geom.AffineTransform) UiContext(games.strategy.triplea.ui.UiContext)

Example 2 with Round

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);
    }
}
Also used : LinkedHashSet(java.util.LinkedHashSet) PlayerID(games.strategy.engine.data.PlayerID) EndRoundDelegate(games.strategy.triplea.delegate.EndRoundDelegate) GameData(games.strategy.engine.data.GameData) DefaultMutableTreeNode(javax.swing.tree.DefaultMutableTreeNode) ArrayList(java.util.ArrayList) ExtendedStats(games.strategy.triplea.ui.ExtendedStats) Step(games.strategy.engine.history.Step) UnitAttachment(games.strategy.triplea.attachments.UnitAttachment) IStat(games.strategy.engine.stats.IStat) ProductionRule(games.strategy.engine.data.ProductionRule) UnitType(games.strategy.engine.data.UnitType) DefaultMutableTreeNode(javax.swing.tree.DefaultMutableTreeNode) TreeNode(javax.swing.tree.TreeNode) Round(games.strategy.engine.history.Round) PlayerOrderComparator(games.strategy.triplea.util.PlayerOrderComparator) Resource(games.strategy.engine.data.Resource) IOException(java.io.IOException) JFileChooser(javax.swing.JFileChooser) HistoryNode(games.strategy.engine.history.HistoryNode) File(java.io.File) Writer(java.io.Writer)

Example 3 with Round

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);
                }
            }
        }
    }
}
Also used : Pattern(java.util.regex.Pattern) PlayerID(games.strategy.engine.data.PlayerID) Matcher(java.util.regex.Matcher) Step(games.strategy.engine.history.Step) Document(javax.swing.text.Document) HistoryNode(games.strategy.engine.history.HistoryNode) TreeNode(javax.swing.tree.TreeNode) Round(games.strategy.engine.history.Round) ImageIcon(javax.swing.ImageIcon) Icon(javax.swing.Icon) BadLocationException(javax.swing.text.BadLocationException)

Example 4 with Round

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();
}
Also used : PlayerID(games.strategy.engine.data.PlayerID) GameData(games.strategy.engine.data.GameData) Enumeration(java.util.Enumeration) ActionEvent(java.awt.event.ActionEvent) HistorySynchronizer(games.strategy.engine.framework.HistorySynchronizer) HistoryLog(games.strategy.triplea.ui.history.HistoryLog) Step(games.strategy.engine.history.Step) IOException(java.io.IOException) HistoryPanel(games.strategy.triplea.ui.history.HistoryPanel) JPopupMenu(javax.swing.JPopupMenu) BorderLayout(java.awt.BorderLayout) HistoryNode(games.strategy.engine.history.HistoryNode) FileOutputStream(java.io.FileOutputStream) Round(games.strategy.engine.history.Round) HistoryDetailsPanel(games.strategy.triplea.ui.history.HistoryDetailsPanel) JSplitPane(javax.swing.JSplitPane) AbstractAction(javax.swing.AbstractAction) File(java.io.File)

Example 5 with Round

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());
}
Also used : DiceRoll(games.strategy.triplea.delegate.DiceRoll) PlayerID(games.strategy.engine.data.PlayerID) DefaultMutableTreeNode(javax.swing.tree.DefaultMutableTreeNode) HashMap(java.util.HashMap) Matcher(java.util.regex.Matcher) ArrayList(java.util.ArrayList) MoveDescription(games.strategy.triplea.delegate.dataObjects.MoveDescription) Step(games.strategy.engine.history.Step) Unit(games.strategy.engine.data.Unit) Renderable(games.strategy.engine.history.Renderable) Round(games.strategy.engine.history.Round) PrintWriter(java.io.PrintWriter) HashSet(java.util.HashSet) IntegerMap(games.strategy.util.IntegerMap) Pattern(java.util.regex.Pattern) Territory(games.strategy.engine.data.Territory) TreePath(javax.swing.tree.TreePath) HistoryNode(games.strategy.engine.history.HistoryNode) Collection(java.util.Collection)

Aggregations

HistoryNode (games.strategy.engine.history.HistoryNode)5 Round (games.strategy.engine.history.Round)5 PlayerID (games.strategy.engine.data.PlayerID)4 Step (games.strategy.engine.history.Step)4 GameData (games.strategy.engine.data.GameData)2 File (java.io.File)2 IOException (java.io.IOException)2 ArrayList (java.util.ArrayList)2 Matcher (java.util.regex.Matcher)2 Pattern (java.util.regex.Pattern)2 DefaultMutableTreeNode (javax.swing.tree.DefaultMutableTreeNode)2 TreeNode (javax.swing.tree.TreeNode)2 ProductionRule (games.strategy.engine.data.ProductionRule)1 Resource (games.strategy.engine.data.Resource)1 Territory (games.strategy.engine.data.Territory)1 Unit (games.strategy.engine.data.Unit)1 UnitType (games.strategy.engine.data.UnitType)1 HistorySynchronizer (games.strategy.engine.framework.HistorySynchronizer)1 Renderable (games.strategy.engine.history.Renderable)1 IStat (games.strategy.engine.stats.IStat)1