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.
}
Aggregations