Search in sources :

Example 6 with Step

use of games.strategy.engine.history.Step in project triplea by triplea-game.

the class BaseEditDelegate method logEvent.

// We don't know the current context, so we need to figure
// out whether it makes more sense to log a new event or a child.
// If any child events came before us, then we'll log a child event.
// Otherwise, we'll log a new event.
void logEvent(final String message, final Object renderingObject) {
    // find last event node
    final GameData gameData = getData();
    gameData.acquireReadLock();
    boolean foundChild = false;
    try {
        HistoryNode curNode = gameData.getHistory().getLastNode();
        while (!(curNode instanceof Step) && !(curNode instanceof Event)) {
            if (curNode instanceof EventChild) {
                foundChild = true;
                break;
            }
            curNode = (HistoryNode) curNode.getPreviousNode();
        }
    } finally {
        gameData.releaseReadLock();
    }
    if (foundChild) {
        bridge.getHistoryWriter().addChildToEvent(message, renderingObject);
    } else {
        bridge.getHistoryWriter().startEvent(message, renderingObject);
    }
}
Also used : GameData(games.strategy.engine.data.GameData) HistoryNode(games.strategy.engine.history.HistoryNode) Event(games.strategy.engine.history.Event) Step(games.strategy.engine.history.Step) EventChild(games.strategy.engine.history.EventChild)

Example 7 with Step

use of games.strategy.engine.history.Step 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 8 with Step

use of games.strategy.engine.history.Step 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 9 with Step

use of games.strategy.engine.history.Step 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)

Example 10 with Step

use of games.strategy.engine.history.Step in project triplea by triplea-game.

the class HistoryLog method printFullTurn.

public void printFullTurn(final GameData data, final boolean verbose, final Collection<PlayerID> playersAllowed) {
    HistoryNode curNode = data.getHistory().getLastNode();
    final Collection<PlayerID> players = new HashSet<>();
    if (playersAllowed != null) {
        players.addAll(playersAllowed);
    }
    // find Step node, if exists in this path
    Step stepNode = null;
    while (curNode != null) {
        if (curNode instanceof Step) {
            stepNode = (Step) curNode;
            break;
        }
        curNode = (HistoryNode) curNode.getPreviousNode();
    }
    if (stepNode != null) {
        final PlayerID curPlayer = stepNode.getPlayerId();
        if (players.isEmpty()) {
            players.add(curPlayer);
        }
        // get first step for this turn
        Step turnStartNode = null;
        while (true) {
            turnStartNode = stepNode;
            stepNode = (Step) stepNode.getPreviousSibling();
            if (stepNode == null) {
                break;
            }
            if (stepNode.getPlayerId() == null) {
                break;
            }
            if (!players.contains(stepNode.getPlayerId())) {
                break;
            }
        }
        printRemainingTurn(turnStartNode, verbose, data.getDiceSides(), players);
    } else {
        System.err.println("No Step node found!");
    }
}
Also used : PlayerID(games.strategy.engine.data.PlayerID) HistoryNode(games.strategy.engine.history.HistoryNode) Step(games.strategy.engine.history.Step) HashSet(java.util.HashSet)

Aggregations

Step (games.strategy.engine.history.Step)10 HistoryNode (games.strategy.engine.history.HistoryNode)8 PlayerID (games.strategy.engine.data.PlayerID)7 GameData (games.strategy.engine.data.GameData)4 Round (games.strategy.engine.history.Round)4 DefaultMutableTreeNode (javax.swing.tree.DefaultMutableTreeNode)4 TreeNode (javax.swing.tree.TreeNode)3 TreePath (javax.swing.tree.TreePath)3 Event (games.strategy.engine.history.Event)2 EventChild (games.strategy.engine.history.EventChild)2 File (java.io.File)2 IOException (java.io.IOException)2 ArrayList (java.util.ArrayList)2 HashSet (java.util.HashSet)2 Matcher (java.util.regex.Matcher)2 Pattern (java.util.regex.Pattern)2 CompositeChange (games.strategy.engine.data.CompositeChange)1 GameStep (games.strategy.engine.data.GameStep)1 ProductionRule (games.strategy.engine.data.ProductionRule)1 Resource (games.strategy.engine.data.Resource)1