Search in sources :

Example 1 with HistoryNode

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

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

the class HistoryLog method getPlayerId.

private static PlayerID getPlayerId(final HistoryNode printNode) {
    DefaultMutableTreeNode curNode = printNode;
    final TreePath parentPath = (new TreePath(printNode.getPath())).getParentPath();
    PlayerID curPlayer = null;
    if (parentPath != null) {
        final Object[] pathToNode = parentPath.getPath();
        for (final Object pathNode : pathToNode) {
            final HistoryNode node = (HistoryNode) pathNode;
            if (node instanceof Step) {
                curPlayer = ((Step) node).getPlayerId();
            }
        }
    }
    do {
        final Enumeration<?> nodeEnum = curNode.preorderEnumeration();
        while (nodeEnum.hasMoreElements()) {
            final HistoryNode node = (HistoryNode) nodeEnum.nextElement();
            if (node instanceof Step) {
                final String title = node.getTitle();
                final PlayerID playerId = ((Step) node).getPlayerId();
                if (!title.equals("Initializing Delegates")) {
                    if (playerId != null) {
                        curPlayer = playerId;
                    }
                }
            }
        }
        curNode = curNode.getNextSibling();
    } while ((curNode instanceof Step) && ((Step) curNode).getPlayerId().equals(curPlayer));
    return curPlayer;
}
Also used : PlayerID(games.strategy.engine.data.PlayerID) DefaultMutableTreeNode(javax.swing.tree.DefaultMutableTreeNode) TreePath(javax.swing.tree.TreePath) HistoryNode(games.strategy.engine.history.HistoryNode) Step(games.strategy.engine.history.Step)

Example 3 with HistoryNode

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

the class HistoryPanel method treeSelectionChanged.

private void treeSelectionChanged(final TreeSelectionEvent e) {
    if (!SwingUtilities.isEventDispatchThread()) {
        throw new IllegalStateException("Wrong thread");
    }
    // move the game to the state of the selected node
    final HistoryNode node = (HistoryNode) e.getPath().getLastPathComponent();
    gotoNode(node);
}
Also used : HistoryNode(games.strategy.engine.history.HistoryNode)

Example 4 with HistoryNode

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

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

the class ServerGame method addPlayerTypesToGameData.

private void addPlayerTypesToGameData(final Collection<IGamePlayer> localPlayers, final PlayerManager allPlayers, final IDelegateBridge bridge) {
    final GameData data = bridge.getData();
    // start before making changes.
    if (getCurrentStep() == null || getCurrentStep().getPlayerId() == null || (firstRun)) {
        firstRun = false;
        return;
    }
    // we can't add a new event or add new changes if we are not in a step.
    final HistoryNode curNode = data.getHistory().getLastNode();
    if (!(curNode instanceof Step) && !(curNode instanceof Event) && !(curNode instanceof EventChild)) {
        return;
    }
    final CompositeChange change = new CompositeChange();
    final Set<String> allPlayersString = allPlayers.getPlayers();
    bridge.getHistoryWriter().startEvent("Game Loaded");
    for (final IGamePlayer player : localPlayers) {
        allPlayersString.remove(player.getName());
        final boolean isHuman = player instanceof TripleAPlayer;
        bridge.getHistoryWriter().addChildToEvent(player.getName() + ((player.getName().endsWith("s") || player.getName().endsWith("ese") || player.getName().endsWith("ish")) ? " are" : " is") + " now being played by: " + player.getType());
        final PlayerID p = data.getPlayerList().getPlayerId(player.getName());
        final String newWhoAmI = ((isHuman ? "Human" : "AI") + ":" + player.getType());
        if (!p.getWhoAmI().equals(newWhoAmI)) {
            change.add(ChangeFactory.changePlayerWhoAmIChange(p, newWhoAmI));
        }
    }
    final Iterator<String> playerIter = allPlayersString.iterator();
    while (playerIter.hasNext()) {
        final String player = playerIter.next();
        playerIter.remove();
        bridge.getHistoryWriter().addChildToEvent(player + ((player.endsWith("s") || player.endsWith("ese") || player.endsWith("ish")) ? " are" : " is") + " now being played by: Human:Client");
        final PlayerID p = data.getPlayerList().getPlayerId(player);
        final String newWhoAmI = "Human:Client";
        if (!p.getWhoAmI().equals(newWhoAmI)) {
            change.add(ChangeFactory.changePlayerWhoAmIChange(p, newWhoAmI));
        }
    }
    if (!change.isEmpty()) {
        bridge.addChange(change);
    }
    needToInitialize = false;
    if (!allPlayersString.isEmpty()) {
        throw new IllegalStateException("Not all Player Types (ai/human/client) could be added to game data.");
    }
}
Also used : IGamePlayer(games.strategy.engine.gamePlayer.IGamePlayer) PlayerID(games.strategy.engine.data.PlayerID) GameData(games.strategy.engine.data.GameData) GameStep(games.strategy.engine.data.GameStep) Step(games.strategy.engine.history.Step) EventChild(games.strategy.engine.history.EventChild) TripleAPlayer(games.strategy.triplea.TripleAPlayer) HistoryNode(games.strategy.engine.history.HistoryNode) Event(games.strategy.engine.history.Event) CompositeChange(games.strategy.engine.data.CompositeChange)

Aggregations

HistoryNode (games.strategy.engine.history.HistoryNode)14 PlayerID (games.strategy.engine.data.PlayerID)9 Step (games.strategy.engine.history.Step)8 GameData (games.strategy.engine.data.GameData)5 Round (games.strategy.engine.history.Round)5 Event (games.strategy.engine.history.Event)3 IOException (java.io.IOException)3 Matcher (java.util.regex.Matcher)3 Pattern (java.util.regex.Pattern)3 TreeNode (javax.swing.tree.TreeNode)3 TreePath (javax.swing.tree.TreePath)3 UnitType (games.strategy.engine.data.UnitType)2 EventChild (games.strategy.engine.history.EventChild)2 UnitAttachment (games.strategy.triplea.attachments.UnitAttachment)2 HistoryPanel (games.strategy.triplea.ui.history.HistoryPanel)2 File (java.io.File)2 HashSet (java.util.HashSet)2 Icon (javax.swing.Icon)2 ImageIcon (javax.swing.ImageIcon)2 BadLocationException (javax.swing.text.BadLocationException)2