Search in sources :

Example 1 with SOCGameStats

use of soc.message.SOCGameStats in project JSettlers2 by jdmonin.

the class SOCGameHandler method sendGameStateOVER.

/**
 *  If game is OVER, send messages reporting winner, final score,
 *  and each player's victory-point cards.
 *  Also give stats on game length, and on each player's connect time.
 *  If player has finished more than 1 game since connecting, send their win-loss count.
 *<P>
 *  Increments server stats' numberOfGamesFinished.
 *  If db is active, calls {@link SOCServer#storeGameScores(SOCGame)} to save game stats.
 *<P>
 *  If {@link SOCGame#isBotsOnly}, calls {@link SOCServer#destroyGameAndBroadcast(String, String)} to make room
 *  for more games to run: The bots don't know on their own to leave, it's easier for the
 *  server to dismiss them within {@code destroyGame}.
 *<P>
 *  Make sure {@link SOCGameState}({@link SOCGame#OVER OVER}) is sent before calling this method.
 *
 * @param ga This game is over; state should be OVER
 * @since 1.1.00
 */
private void sendGameStateOVER(SOCGame ga) {
    final String gname = ga.getName();
    /**
     * Find and announce the winner
     * (the real "found winner" code is in SOCGame.checkForWinner;
     *  that was already called before sendGameStateOVER.)
     */
    SOCPlayer winPl = ga.getPlayer(ga.getCurrentPlayerNumber());
    if ((winPl.getTotalVP() < ga.vp_winner) && !ga.hasScenarioWinCondition) {
        // This is fallback code.
        for (int i = 0; i < ga.maxPlayers; i++) {
            if (winPl.getTotalVP() >= ga.vp_winner) {
                winPl = ga.getPlayer(i);
                break;
            }
        }
    }
    srv.messageToGameKeyed(ga, true, "stats.game.winner.withpoints", winPl.getName(), winPl.getTotalVP());
    // "{0} has won the game with {1,number} points."
    // / send a message with the revealed final scores
    {
        int[] scores = new int[ga.maxPlayers];
        boolean[] isRobot = new boolean[ga.maxPlayers];
        for (int i = 0; i < ga.maxPlayers; ++i) {
            scores[i] = ga.getPlayer(i).getTotalVP();
            isRobot[i] = ga.getPlayer(i).isRobot();
        }
        srv.messageToGame(gname, new SOCGameStats(gname, scores, isRobot));
    }
    // /
    for (int i = 0; i < ga.maxPlayers; i++) {
        SOCPlayer pl = ga.getPlayer(i);
        List<SOCInventoryItem> vpCards = pl.getInventory().getByState(SOCInventory.KEPT);
        if (!vpCards.isEmpty())
            srv.messageToGameKeyedSpecial(ga, true, "endgame.player.has.vpcards", pl.getName(), vpCards);
    // "Joe has a Gov.House (+1VP) and a Market (+1VP)" ["{0} has {1,dcards}."]
    }
    // for each player
    /**
     * send game-length and connect-length messages, possibly win-loss count.
     */
    {
        Date now = new Date();
        Date gstart = ga.getStartTime();
        if (gstart != null) {
            final int gameRounds = ga.getRoundCount();
            long gameSeconds = ((now.getTime() - gstart.getTime()) + 500L) / 1000L;
            final long gameMinutes = gameSeconds / 60L;
            gameSeconds = gameSeconds % 60L;
            if (gameSeconds == 0)
                srv.messageToGameKeyed(ga, true, "stats.game.was.roundsminutes", gameRounds, gameMinutes);
            else
                // "This game was # rounds, and took # minutes."
                srv.messageToGameKeyed(ga, true, "stats.game.was.roundsminutessec", gameRounds, gameMinutes, gameSeconds);
        // "This game was # rounds, and took # minutes # seconds." [or 1 second.]
        // Ignore possible "1 minutes"; that game is too short to worry about.
        }
        /**
         * Update each player's win-loss count for this session.
         * Tell each player their resource roll totals.
         * Tell each player how long they've been connected.
         * (Robot players aren't told this, it's not necessary.)
         */
        final String connMsgKey;
        if (ga.isPractice)
            // "You have been practicing # minutes."
            connMsgKey = "stats.cli.connected.minutes.prac";
        else
            // "You have been connected # minutes."
            connMsgKey = "stats.cli.connected.minutes";
        for (int i = 0; i < ga.maxPlayers; i++) {
            if (ga.isSeatVacant(i))
                continue;
            SOCPlayer pl = ga.getPlayer(i);
            Connection plConn = srv.getConnection(pl.getName());
            SOCClientData cd;
            if (plConn != null) {
                // Update win-loss count, even for robots
                cd = (SOCClientData) plConn.getAppData();
                if (pl == winPl)
                    cd.wonGame();
                else
                    cd.lostGame();
            } else {
                // To satisfy compiler warning
                cd = null;
            }
            if (pl.isRobot())
                // <-- Don't bother to send any stats text to robots --
                continue;
            if (plConn != null) {
                if (plConn.getVersion() >= SOCPlayerStats.VERSION_FOR_RES_ROLL) {
                    // Send total resources rolled
                    srv.messageToPlayer(plConn, new SOCPlayerStats(pl, SOCPlayerStats.STYPE_RES_ROLL));
                }
                final long connTime = plConn.getConnectTime().getTime();
                final long connMinutes = (((now.getTime() - connTime)) + 30000L) / 60000L;
                // "You have been connected # minutes."
                srv.messageToPlayerKeyed(plConn, gname, connMsgKey, connMinutes);
                // Send client's win-loss count for this session,
                // if more than 1 game has been played
                {
                    int wins = cd.getWins();
                    int losses = cd.getLosses();
                    if (wins + losses < 2)
                        // Only 1 game played so far
                        continue;
                    if (wins > 0) {
                        if (losses == 0)
                            srv.messageToPlayerKeyed(plConn, gname, "stats.cli.winloss.won", wins);
                        else
                            // "You have won {0,choice, 1#1 game|1<{0,number} games} since connecting."
                            srv.messageToPlayerKeyed(plConn, gname, "stats.cli.winloss.wonlost", wins, losses);
                    // "You have won {0,choice, 1#1 game|1<{0,number} games} and lost {1,choice, 1#1 game|1<{1,number} games} since connecting."
                    } else {
                        srv.messageToPlayerKeyed(plConn, gname, "stats.cli.winloss.lost", losses);
                    // "You have lost {0,choice, 1#1 game|1<{0,number} games} since connecting."
                    }
                }
            }
        }
    // for each player
    }
    // send game timing stats, win-loss stats
    srv.gameOverIncrGamesFinishedCount();
    srv.storeGameScores(ga);
    if (ga.isBotsOnly) {
        srv.destroyGameAndBroadcast(gname, "sendGameStateOVER");
    }
// Server structure more or less ensures sendGameStateOVER is called only once.
// TODO consider refactor to be completely sure, especially for storeGameScores.
}
Also used : Connection(soc.server.genericServer.Connection) SOCPlayerStats(soc.message.SOCPlayerStats) Date(java.util.Date) SOCGameStats(soc.message.SOCGameStats)

Aggregations

Date (java.util.Date)1 SOCGameStats (soc.message.SOCGameStats)1 SOCPlayerStats (soc.message.SOCPlayerStats)1 Connection (soc.server.genericServer.Connection)1