Add user client information to user metrics info (language, device class, name).
Add metrics logging for server start up, user disconnect, and card judging events.
This commit is contained in:
parent
e1bc2c4176
commit
45690c1914
|
@ -108,6 +108,9 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
|
||||
<h2>Server</h2>
|
||||
|
||||
This product includes GeoLite2 data created by MaxMind, available from
|
||||
<a href="http://www.maxmind.com">http://www.maxmind.com</a>.
|
||||
|
||||
<h3>ANTLR</h3>
|
||||
Copyright (c) 2010 Terence Parr
|
||||
<br /> All rights reserved.
|
||||
|
|
10
pom.xml
10
pom.xml
|
@ -353,5 +353,15 @@
|
|||
<artifactId>geoip2</artifactId>
|
||||
<version>2.8.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.sf.uadetector</groupId>
|
||||
<artifactId>uadetector-core</artifactId>
|
||||
<version>0.9.22</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.sf.uadetector</groupId>
|
||||
<artifactId>uadetector-resources</artifactId>
|
||||
<version>2014.10</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (c) 2012, Andy Janata
|
||||
* Copyright (c) 2012-2017, Andy Janata
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||
|
@ -57,6 +57,18 @@ public class RequestWrapper {
|
|||
return request.getParameter(parameter.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of a request header as a String, or {@code null} if the header does not
|
||||
* exist.
|
||||
*
|
||||
* @param header
|
||||
* Header to get.
|
||||
* @return Value of header, or {@code null} if header does not exist.
|
||||
*/
|
||||
public String getHeader(final String header) {
|
||||
return request.getHeader(header);
|
||||
}
|
||||
|
||||
/**
|
||||
* If there is an {@code X-Forwarded-For} header, the <strong>first</strong> entry in that list
|
||||
* is returned instead.
|
||||
|
|
|
@ -34,8 +34,10 @@ import javax.servlet.ServletContext;
|
|||
import javax.servlet.ServletContextEvent;
|
||||
|
||||
import net.socialgamer.cah.CahModule.ServerStarted;
|
||||
import net.socialgamer.cah.CahModule.UniqueId;
|
||||
import net.socialgamer.cah.cardcast.CardcastModule;
|
||||
import net.socialgamer.cah.cardcast.CardcastService;
|
||||
import net.socialgamer.cah.metrics.Metrics;
|
||||
import net.socialgamer.cah.task.BroadcastGameListUpdateTask;
|
||||
import net.socialgamer.cah.task.UserPingTask;
|
||||
|
||||
|
@ -131,6 +133,10 @@ public class StartupUtils extends GuiceServletContextListener {
|
|||
reconfigureLogging(contextEvent.getServletContext());
|
||||
reloadProperties(contextEvent.getServletContext());
|
||||
CardcastService.hackSslVerifier();
|
||||
|
||||
// log that the server (re-)started to metrics logging (to flush all old games and users)
|
||||
injector.getInstance(Metrics.class).serverStarted(
|
||||
injector.getInstance(Key.get(String.class, UniqueId.class)));
|
||||
}
|
||||
|
||||
public static void reloadProperties(final ServletContext context) {
|
||||
|
|
|
@ -142,7 +142,8 @@ public class ConnectedUsers {
|
|||
logger.warn(String.format("Unable to get address for user %s (hostname: %s)",
|
||||
user.getNickname(), user.getHostname()), e);
|
||||
}
|
||||
metrics.newUser(user.getPersistentId(), user.getSessionId(), geo);
|
||||
metrics.newUser(user.getPersistentId(), user.getSessionId(), geo, user.getAgentName(),
|
||||
user.getAgentType(), user.getAgentOs(), user.getAgentLanguage());
|
||||
|
||||
return null;
|
||||
}
|
||||
|
@ -162,7 +163,7 @@ public class ConnectedUsers {
|
|||
synchronized (users) {
|
||||
if (users.containsKey(user.getNickname())) {
|
||||
logger.info(String.format("Removing user %s because %s", user.toString(), reason));
|
||||
user.noLongerVaild();
|
||||
user.noLongerValid();
|
||||
users.remove(user.getNickname().toLowerCase());
|
||||
notifyRemoveUser(user, reason);
|
||||
}
|
||||
|
@ -181,7 +182,7 @@ public class ConnectedUsers {
|
|||
}
|
||||
|
||||
/**
|
||||
* Broadcast to all remaining users that a user has left.
|
||||
* Broadcast to all remaining users that a user has left. Also logs for metrics.
|
||||
*
|
||||
* @param user
|
||||
* User that has left.
|
||||
|
@ -197,6 +198,8 @@ public class ConnectedUsers {
|
|||
data.put(LongPollResponse.REASON, reason.toString());
|
||||
broadcastToAll(MessageType.PLAYER_EVENT, data);
|
||||
}
|
||||
|
||||
metrics.userDisconnect(user.getSessionId());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -226,7 +229,7 @@ public class ConnectedUsers {
|
|||
// Do this later to not keep users locked
|
||||
for (final Entry<User, DisconnectReason> entry : removedUsers.entrySet()) {
|
||||
try {
|
||||
entry.getKey().noLongerVaild();
|
||||
entry.getKey().noLongerValid();
|
||||
notifyRemoveUser(entry.getKey(), entry.getValue());
|
||||
logger.info(String.format("Automatically kicking user %s due to %s", entry.getKey(),
|
||||
entry.getValue()));
|
||||
|
|
|
@ -56,8 +56,10 @@ import net.socialgamer.cah.cardcast.CardcastDeck;
|
|||
import net.socialgamer.cah.cardcast.CardcastService;
|
||||
import net.socialgamer.cah.data.GameManager.GameId;
|
||||
import net.socialgamer.cah.data.QueuedMessage.MessageType;
|
||||
import net.socialgamer.cah.metrics.Metrics;
|
||||
import net.socialgamer.cah.task.SafeTimerTask;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.hibernate.Session;
|
||||
|
||||
|
@ -109,6 +111,7 @@ public class Game {
|
|||
private GameState state;
|
||||
private final GameOptions options = new GameOptions();
|
||||
private final Set<String> cardcastDeckIds = Collections.synchronizedSet(new HashSet<String>());
|
||||
private final Metrics metrics;
|
||||
|
||||
private int judgeIndex = 0;
|
||||
|
||||
|
@ -194,7 +197,8 @@ public class Game {
|
|||
final GameManager gameManager, final ScheduledThreadPoolExecutor globalTimer,
|
||||
final Provider<Session> sessionProvider,
|
||||
final Provider<CardcastService> cardcastServiceProvider,
|
||||
@UniqueId final Provider<String> uniqueIdProvider) {
|
||||
@UniqueId final Provider<String> uniqueIdProvider,
|
||||
final Metrics metrics) {
|
||||
this.id = id;
|
||||
this.connectedUsers = connectedUsers;
|
||||
this.gameManager = gameManager;
|
||||
|
@ -202,6 +206,7 @@ public class Game {
|
|||
this.sessionProvider = sessionProvider;
|
||||
this.cardcastServiceProvider = cardcastServiceProvider;
|
||||
this.uniqueIdProvider = uniqueIdProvider;
|
||||
this.metrics = metrics;
|
||||
|
||||
state = GameState.LOBBY;
|
||||
}
|
||||
|
@ -683,10 +688,14 @@ public class Game {
|
|||
options.spectatorLimit, options.scoreGoal, players, currentUniqueId));
|
||||
// do this stuff outside the players lock; they will lock players again later for much less
|
||||
// time, and not at the same time as trying to lock users, which has caused deadlocks
|
||||
final List<CardSet> cardSets;
|
||||
synchronized (options.cardSetIds) {
|
||||
blackDeck = loadBlackDeck(session);
|
||||
whiteDeck = loadWhiteDeck(session);
|
||||
cardSets = loadCardSets(session);
|
||||
blackDeck = loadBlackDeck(cardSets);
|
||||
whiteDeck = loadWhiteDeck(cardSets);
|
||||
}
|
||||
metrics.gameStart(currentUniqueId, cardSets, options.blanksInDeck, options.playerLimit,
|
||||
options.scoreGoal, !StringUtils.isBlank(options.password));
|
||||
startNextRound();
|
||||
gameManager.broadcastGameListRefresh();
|
||||
}
|
||||
|
@ -698,7 +707,7 @@ public class Game {
|
|||
}
|
||||
}
|
||||
|
||||
private List<CardSet> loadCardSets(final Session session) {
|
||||
public List<CardSet> loadCardSets(final Session session) {
|
||||
synchronized (options.cardSetIds) {
|
||||
try {
|
||||
final List<CardSet> cardSets = new ArrayList<>();
|
||||
|
@ -738,12 +747,12 @@ public class Game {
|
|||
}
|
||||
}
|
||||
|
||||
public BlackDeck loadBlackDeck(final Session session) {
|
||||
return new BlackDeck(loadCardSets(session));
|
||||
public BlackDeck loadBlackDeck(final List<CardSet> cardSets) {
|
||||
return new BlackDeck(cardSets);
|
||||
}
|
||||
|
||||
public WhiteDeck loadWhiteDeck(final Session session) {
|
||||
return new WhiteDeck(loadCardSets(session), options.blanksInDeck);
|
||||
public WhiteDeck loadWhiteDeck(final List<CardSet> cardSets) {
|
||||
return new WhiteDeck(cardSets, options.blanksInDeck);
|
||||
}
|
||||
|
||||
public int getRequiredWhiteCardCount() {
|
||||
|
@ -752,21 +761,21 @@ public class Game {
|
|||
|
||||
/**
|
||||
* Determine if there are sufficient cards in the selected card sets to start the game.
|
||||
* <p>This could be done more efficiently as we're ending up loading the decks multiple times
|
||||
* with different Sessions, so caching wouldn't help local decks.
|
||||
*/
|
||||
public boolean hasEnoughCards(final Session session) {
|
||||
synchronized (options.cardSetIds) {
|
||||
if (options.cardSetIds.isEmpty() && cardcastDeckIds.isEmpty()) {
|
||||
final List<CardSet> cardSets = loadCardSets(session);
|
||||
|
||||
if (cardSets.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final BlackDeck tempBlackDeck = loadBlackDeck(session);
|
||||
final BlackDeck tempBlackDeck = loadBlackDeck(cardSets);
|
||||
if (tempBlackDeck.totalCount() < MINIMUM_BLACK_CARDS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final WhiteDeck tempWhiteDeck = loadWhiteDeck(session);
|
||||
final WhiteDeck tempWhiteDeck = loadWhiteDeck(cardSets);
|
||||
if (tempWhiteDeck.totalCount() < getRequiredWhiteCardCount()) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1503,6 +1512,9 @@ public class Game {
|
|||
rescheduleTimer(task, ROUND_INTERMISSION);
|
||||
}
|
||||
|
||||
metrics.roundJudged(currentUniqueId, user.getSessionId(), cardPlayer.getUser().getSessionId(),
|
||||
playedCards.cardsByUser());
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (c) 2012, Andy Janata
|
||||
* Copyright (c) 2012-2017, Andy Janata
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||
|
@ -25,13 +25,12 @@ package net.socialgamer.cah.data;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import net.socialgamer.cah.data.WhiteCard;
|
||||
|
||||
|
||||
/**
|
||||
* Class to track which card(s) have been played by players. Can get the card(s) for a player, and
|
||||
|
@ -143,4 +142,16 @@ public class PlayerPlayedCardsTracker {
|
|||
public synchronized Collection<List<WhiteCard>> cards() {
|
||||
return playerCardMap.values();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return A {@code Map} of users to a {@code List} of the cards they played.
|
||||
*/
|
||||
public synchronized Map<User, List<WhiteCard>> cardsByUser() {
|
||||
final Map<User, List<WhiteCard>> cardsByUser = new HashMap<>();
|
||||
// TODO java8: streams
|
||||
for (final Map.Entry<Player, List<WhiteCard>> entry : playerCardMap.entrySet()) {
|
||||
cardsByUser.put(entry.getKey().getUser(), entry.getValue());
|
||||
}
|
||||
return Collections.unmodifiableMap(cardsByUser);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,6 +30,8 @@ import java.util.LinkedList;
|
|||
import java.util.List;
|
||||
import java.util.concurrent.PriorityBlockingQueue;
|
||||
|
||||
import net.sf.uadetector.ReadableUserAgent;
|
||||
import net.sf.uadetector.service.UADetectorServiceFactory;
|
||||
import net.socialgamer.cah.CahModule.UniqueId;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
|
@ -63,6 +65,10 @@ public class User {
|
|||
|
||||
private final String sessionId;
|
||||
|
||||
private final String clientLanguage;
|
||||
|
||||
private final ReadableUserAgent agent;
|
||||
|
||||
private final List<Long> lastMessageTimes = Collections.synchronizedList(new LinkedList<Long>());
|
||||
|
||||
/**
|
||||
|
@ -89,18 +95,24 @@ public class User {
|
|||
@Assisted("hostname") final String hostname,
|
||||
@Assisted final boolean isAdmin,
|
||||
@Assisted("persistentId") final String persistentId,
|
||||
@UniqueId final String sessionId) {
|
||||
@UniqueId final String sessionId,
|
||||
@Assisted("clientLanguage") final String clientLanguage,
|
||||
@Assisted("clientAgent") final String clientAgent) {
|
||||
this.nickname = nickname;
|
||||
this.hostname = hostname;
|
||||
this.isAdmin = isAdmin;
|
||||
this.persistentId = persistentId;
|
||||
this.sessionId = sessionId;
|
||||
this.clientLanguage = clientLanguage;
|
||||
agent = UADetectorServiceFactory.getResourceModuleParser().parse(clientAgent);
|
||||
queuedMessages = new PriorityBlockingQueue<QueuedMessage>();
|
||||
}
|
||||
|
||||
public interface Factory {
|
||||
User create(@Assisted("nickname") String nickname, @Assisted("hostname") String hostname,
|
||||
boolean isAdmin, @Assisted("persistentId") String persistentId);
|
||||
boolean isAdmin, @Assisted("persistentId") String persistentId,
|
||||
@Assisted("clientLanguage") String clientLanguage,
|
||||
@Assisted("clientAgent") String clientAgent);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -193,6 +205,22 @@ public class User {
|
|||
return hostname;
|
||||
}
|
||||
|
||||
public String getAgentName() {
|
||||
return agent.getName();
|
||||
}
|
||||
|
||||
public String getAgentType() {
|
||||
return agent.getDeviceCategory().getName();
|
||||
}
|
||||
|
||||
public String getAgentOs() {
|
||||
return agent.getOperatingSystem().getName();
|
||||
}
|
||||
|
||||
public String getAgentLanguage() {
|
||||
return clientLanguage.split(",")[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getNickname();
|
||||
|
@ -230,7 +258,7 @@ public class User {
|
|||
/**
|
||||
* Mark this user as no longer valid, probably because they pinged out.
|
||||
*/
|
||||
public void noLongerVaild() {
|
||||
public void noLongerValid() {
|
||||
if (currentGame != null) {
|
||||
currentGame.removePlayer(this);
|
||||
}
|
||||
|
|
|
@ -63,7 +63,7 @@ public class LogoutHandler extends Handler {
|
|||
final User user = (User) session.getAttribute(SessionAttribute.USER);
|
||||
assert (user != null);
|
||||
|
||||
user.noLongerVaild();
|
||||
user.noLongerValid();
|
||||
users.removeUser(user, DisconnectReason.MANUAL);
|
||||
session.invalidate();
|
||||
return data;
|
||||
|
|
|
@ -44,6 +44,7 @@ import net.socialgamer.cah.data.ConnectedUsers;
|
|||
import net.socialgamer.cah.data.User;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.http.HttpHeaders;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
|
@ -99,7 +100,9 @@ public class RegisterHandler extends Handler {
|
|||
}
|
||||
|
||||
final User user = userFactory.create(nick, request.getRemoteAddr(),
|
||||
Constants.ADMIN_IP_ADDRESSES.contains(request.getRemoteAddr()), persistentId);
|
||||
Constants.ADMIN_IP_ADDRESSES.contains(request.getRemoteAddr()), persistentId,
|
||||
request.getHeader(HttpHeaders.ACCEPT_LANGUAGE),
|
||||
request.getHeader(HttpHeaders.USER_AGENT));
|
||||
final ErrorCode errorCode = users.checkAndAdd(user);
|
||||
if (null == errorCode) {
|
||||
// There is a findbugs warning on this line:
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (c) 2012, Andy Janata
|
||||
* Copyright (c) 2012-2017, Andy Janata
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||
|
@ -24,6 +24,7 @@
|
|||
package net.socialgamer.cah.handlers;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
@ -34,6 +35,7 @@ import net.socialgamer.cah.Constants.ErrorInformation;
|
|||
import net.socialgamer.cah.Constants.GameState;
|
||||
import net.socialgamer.cah.Constants.ReturnableData;
|
||||
import net.socialgamer.cah.RequestWrapper;
|
||||
import net.socialgamer.cah.data.CardSet;
|
||||
import net.socialgamer.cah.data.Game;
|
||||
import net.socialgamer.cah.data.GameManager;
|
||||
import net.socialgamer.cah.data.User;
|
||||
|
@ -72,11 +74,10 @@ public class StartGameHandler extends GameWithPlayerHandler {
|
|||
} else if (game.getState() != GameState.LOBBY) {
|
||||
return error(ErrorCode.ALREADY_STARTED);
|
||||
} else if (!game.hasEnoughCards(hibernateSession)) {
|
||||
data.put(ErrorInformation.BLACK_CARDS_PRESENT, game.loadBlackDeck(hibernateSession)
|
||||
.totalCount());
|
||||
final List<CardSet> cardSets = game.loadCardSets(hibernateSession);
|
||||
data.put(ErrorInformation.BLACK_CARDS_PRESENT, game.loadBlackDeck(cardSets).totalCount());
|
||||
data.put(ErrorInformation.BLACK_CARDS_REQUIRED, Game.MINIMUM_BLACK_CARDS);
|
||||
data.put(ErrorInformation.WHITE_CARDS_PRESENT, game.loadWhiteDeck(hibernateSession)
|
||||
.totalCount());
|
||||
data.put(ErrorInformation.WHITE_CARDS_PRESENT, game.loadWhiteDeck(cardSets).totalCount());
|
||||
data.put(ErrorInformation.WHITE_CARDS_REQUIRED, game.getRequiredWhiteCardCount());
|
||||
return error(ErrorCode.NOT_ENOUGH_CARDS, data);
|
||||
} else if (!game.start()) {
|
||||
|
|
|
@ -23,6 +23,14 @@
|
|||
|
||||
package net.socialgamer.cah.metrics;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import net.socialgamer.cah.data.CardSet;
|
||||
import net.socialgamer.cah.data.User;
|
||||
import net.socialgamer.cah.data.WhiteCard;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.google.inject.Singleton;
|
||||
|
@ -40,7 +48,35 @@ public class KafkaMetrics implements Metrics {
|
|||
private static final Logger LOG = Logger.getLogger(KafkaMetrics.class);
|
||||
|
||||
@Override
|
||||
public void newUser(final String guid, final String sessionId, final CityResponse geoIp) {
|
||||
LOG.trace(String.format("newUser(%s, %s, %s)", guid, sessionId, geoIp));
|
||||
public void serverStarted(final String startupId) {
|
||||
LOG.trace(String.format("serverStarted(%s)", startupId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void newUser(final String guid, final String sessionId, final CityResponse geoIp,
|
||||
final String agentName, final String agentType, final String agentOs,
|
||||
final String agentLanguage) {
|
||||
LOG.trace(String.format("newUser(%s, %s, %s, %s, %s, %s, %s)", guid, sessionId, geoIp,
|
||||
agentName, agentType, agentOs, agentLanguage));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void userDisconnect(final String sessionId) {
|
||||
LOG.trace(String.format("userDisconnect(%s)", sessionId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void gameStart(final String gameId, final Collection<CardSet> decks, final int blanks,
|
||||
final int maxPlayers, final int scoreGoal, final boolean hasPassword) {
|
||||
LOG.trace(String.format("gameStart(%s, %s, %d, %d, %d, %s)", gameId, decks.toArray(), blanks,
|
||||
maxPlayers, scoreGoal, hasPassword));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void roundJudged(final String gameId, final String judgeSessionId,
|
||||
final String winnerSessionId,
|
||||
final Map<User, List<WhiteCard>> cards) {
|
||||
LOG.trace(String.format("roundJudged(%s, %s, %s, %s)", gameId, judgeSessionId, winnerSessionId,
|
||||
cards));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,8 +23,16 @@
|
|||
|
||||
package net.socialgamer.cah.metrics;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import net.socialgamer.cah.data.CardSet;
|
||||
import net.socialgamer.cah.data.User;
|
||||
import net.socialgamer.cah.data.WhiteCard;
|
||||
|
||||
import com.maxmind.geoip2.model.CityResponse;
|
||||
|
||||
|
||||
|
@ -34,5 +42,18 @@ import com.maxmind.geoip2.model.CityResponse;
|
|||
* @author Andy Janata (ajanata@socialgamer.net)
|
||||
*/
|
||||
public interface Metrics {
|
||||
void newUser(String persistentId, String sessionId, @Nullable CityResponse geoIp);
|
||||
void serverStarted(String startupId);
|
||||
|
||||
void newUser(String persistentId, String sessionId, @Nullable CityResponse geoIp,
|
||||
String agentName, String agentType, String agentOs, String agentLanguage);
|
||||
|
||||
void userDisconnect(String sessionId);
|
||||
|
||||
// The card data is way too complicated to dictate the format it should be in, so let
|
||||
// implementations deal with the structured data.
|
||||
void roundJudged(String gameId, String judgeSessionId, String winnerSessionId,
|
||||
Map<User, List<WhiteCard>> cards);
|
||||
|
||||
void gameStart(String gameId, Collection<CardSet> decks, int blanks, int maxPlayers,
|
||||
int scoreGoal, boolean hasPassword);
|
||||
}
|
||||
|
|
|
@ -23,6 +23,14 @@
|
|||
|
||||
package net.socialgamer.cah.metrics;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import net.socialgamer.cah.data.CardSet;
|
||||
import net.socialgamer.cah.data.User;
|
||||
import net.socialgamer.cah.data.WhiteCard;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.google.inject.Singleton;
|
||||
|
@ -40,7 +48,35 @@ public class NoOpMetrics implements Metrics {
|
|||
private static final Logger LOG = Logger.getLogger(NoOpMetrics.class);
|
||||
|
||||
@Override
|
||||
public void newUser(final String guid, final String sessionId, final CityResponse geoIp) {
|
||||
LOG.trace(String.format("newUser(%s, %s, %s)", guid, sessionId, geoIp));
|
||||
public void serverStarted(final String startupId) {
|
||||
LOG.trace(String.format("serverStarted(%s)", startupId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void newUser(final String guid, final String sessionId, final CityResponse geoIp,
|
||||
final String agentName, final String agentType, final String agentOs,
|
||||
final String agentLanguage) {
|
||||
LOG.trace(String.format("newUser(%s, %s, %s, %s, %s, %s, %s)", guid, sessionId, geoIp,
|
||||
agentName, agentType, agentOs, agentLanguage));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void userDisconnect(final String sessionId) {
|
||||
LOG.trace(String.format("userDisconnect(%s)", sessionId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void gameStart(final String gameId, final Collection<CardSet> decks, final int blanks,
|
||||
final int maxPlayers, final int scoreGoal, final boolean hasPassword) {
|
||||
LOG.trace(String.format("gameStart(%s, %s, %d, %d, %d, %s)", gameId, decks.toArray(), blanks,
|
||||
maxPlayers, scoreGoal, hasPassword));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void roundJudged(final String gameId, final String judgeSessionId,
|
||||
final String winnerSessionId,
|
||||
final Map<User, List<WhiteCard>> cards) {
|
||||
LOG.trace(String.format("roundJudged(%s, %s, %s, %s)", gameId, judgeSessionId, winnerSessionId,
|
||||
cards));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,6 +45,7 @@ import net.socialgamer.cah.cardcast.CardcastModule.CardcastCardId;
|
|||
import net.socialgamer.cah.data.GameManager.GameId;
|
||||
import net.socialgamer.cah.data.GameManager.MaxGames;
|
||||
import net.socialgamer.cah.data.QueuedMessage.MessageType;
|
||||
import net.socialgamer.cah.metrics.Metrics;
|
||||
|
||||
import org.hibernate.Session;
|
||||
import org.junit.After;
|
||||
|
@ -70,11 +71,13 @@ public class GameManagerTest {
|
|||
private User userMock;
|
||||
private int gameId;
|
||||
private final ScheduledThreadPoolExecutor timer = new ScheduledThreadPoolExecutor(1);
|
||||
private Metrics metricsMock;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
cuMock = createMock(ConnectedUsers.class);
|
||||
userMock = createMock(User.class);
|
||||
metricsMock = createMock(Metrics.class);
|
||||
|
||||
injector = Guice.createInjector(new AbstractModule() {
|
||||
@Override
|
||||
|
@ -143,11 +146,14 @@ public class GameManagerTest {
|
|||
|
||||
// fill it up with 3 games
|
||||
assertEquals(0, gameManager.get().intValue());
|
||||
gameManager.getGames().put(0, new Game(0, cuMock, gameManager, timer, null, null, null));
|
||||
gameManager.getGames().put(0,
|
||||
new Game(0, cuMock, gameManager, timer, null, null, null, metricsMock));
|
||||
assertEquals(1, gameManager.get().intValue());
|
||||
gameManager.getGames().put(1, new Game(1, cuMock, gameManager, timer, null, null, null));
|
||||
gameManager.getGames().put(1,
|
||||
new Game(1, cuMock, gameManager, timer, null, null, null, metricsMock));
|
||||
assertEquals(2, gameManager.get().intValue());
|
||||
gameManager.getGames().put(2, new Game(2, cuMock, gameManager, timer, null, null, null));
|
||||
gameManager.getGames().put(2,
|
||||
new Game(2, cuMock, gameManager, timer, null, null, null, metricsMock));
|
||||
// make sure it says it can't make any more
|
||||
assertEquals(-1, gameManager.get().intValue());
|
||||
|
||||
|
@ -155,13 +161,15 @@ public class GameManagerTest {
|
|||
gameManager.destroyGame(1);
|
||||
// make sure it re-uses that id
|
||||
assertEquals(1, gameManager.get().intValue());
|
||||
gameManager.getGames().put(1, new Game(1, cuMock, gameManager, timer, null, null, null));
|
||||
gameManager.getGames().put(1,
|
||||
new Game(1, cuMock, gameManager, timer, null, null, null, metricsMock));
|
||||
assertEquals(-1, gameManager.get().intValue());
|
||||
|
||||
// remove game 1 out from under it, to make sure it'll fix itself
|
||||
gameManager.getGames().remove(1);
|
||||
assertEquals(1, gameManager.get().intValue());
|
||||
gameManager.getGames().put(1, new Game(1, cuMock, gameManager, timer, null, null, null));
|
||||
gameManager.getGames().put(1,
|
||||
new Game(1, cuMock, gameManager, timer, null, null, null, metricsMock));
|
||||
assertEquals(-1, gameManager.get().intValue());
|
||||
|
||||
gameManager.destroyGame(2);
|
||||
|
|
|
@ -40,6 +40,7 @@ import java.util.concurrent.ScheduledThreadPoolExecutor;
|
|||
|
||||
import net.socialgamer.cah.data.Game.TooManyPlayersException;
|
||||
import net.socialgamer.cah.data.QueuedMessage.MessageType;
|
||||
import net.socialgamer.cah.metrics.Metrics;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
@ -55,13 +56,15 @@ public class GameTest {
|
|||
private Game game;
|
||||
private ConnectedUsers cuMock;
|
||||
private GameManager gmMock;
|
||||
private Metrics metricsMock;
|
||||
private final ScheduledThreadPoolExecutor timer = new ScheduledThreadPoolExecutor(1);
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
cuMock = createMock(ConnectedUsers.class);
|
||||
gmMock = createMock(GameManager.class);
|
||||
game = new Game(0, cuMock, gmMock, timer, null, null, null);
|
||||
metricsMock = createMock(Metrics.class);
|
||||
game = new Game(0, cuMock, gmMock, timer, null, null, null, metricsMock);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
@ -75,8 +78,8 @@ public class GameTest {
|
|||
expectLastCall().once();
|
||||
replay(gmMock);
|
||||
|
||||
final User user1 = new User("test1", "test.lan", false, "1", "1");
|
||||
final User user2 = new User("test2", "test.lan", false, "2", "2");
|
||||
final User user1 = new User("test1", "test.lan", false, "1", "1", "en-US", "JUnit");
|
||||
final User user2 = new User("test2", "test.lan", false, "2", "2", "en-US", "JUnit");
|
||||
game.addPlayer(user1);
|
||||
game.addPlayer(user2);
|
||||
|
||||
|
|
Loading…
Reference in New Issue