Adding clocks on server side and cleaning up finished games after 5 minutes.
This commit is contained in:
@@ -5,6 +5,7 @@ import com.gempukku.lotro.logic.decisions.AwaitingDecision;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class DefaultUserFeedback implements UserFeedback {
|
||||
private Map<String, AwaitingDecision> _awaitingDecisionMap = new HashMap<String, AwaitingDecision>();
|
||||
@@ -36,4 +37,8 @@ public class DefaultUserFeedback implements UserFeedback {
|
||||
public void sendWarning(String playerId, String warning) {
|
||||
_warnings.put(playerId, warning);
|
||||
}
|
||||
|
||||
public Set<String> getUsersPendingDecision() {
|
||||
return _awaitingDecisionMap.keySet();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,9 @@ public class LotroGameMediator {
|
||||
private Map<String, GatheringParticipantCommunicationChannel> _communicationChannels = new HashMap<String, GatheringParticipantCommunicationChannel>();
|
||||
private DefaultUserFeedback _userFeedback = new DefaultUserFeedback();
|
||||
private DefaultLotroGame _lotroGame;
|
||||
private Map<String, Integer> _playerClocks = new HashMap<String, Integer>();
|
||||
private Map<String, Long> _decisionQuerySentTimes = new HashMap<String, Long>();
|
||||
private final int _maxSecondsPerPlayer = 60 * 30; // 30 minutes
|
||||
|
||||
public LotroGameMediator(LotroFormat lotroFormat, LotroGameParticipant[] participants, LotroCardBlueprintLibrary library, GameResultListener gameResultListener) {
|
||||
if (participants.length < 1)
|
||||
@@ -31,6 +34,7 @@ public class LotroGameMediator {
|
||||
String participantId = participant.getPlayerId();
|
||||
participantSet.add(participantId);
|
||||
decks.put(participantId, participant.getDeck());
|
||||
_playerClocks.put(participantId, 0);
|
||||
}
|
||||
_lotroGame = new DefaultLotroGame(decks, _userFeedback, gameResultListener, library);
|
||||
}
|
||||
@@ -78,7 +82,13 @@ public class LotroGameMediator {
|
||||
try {
|
||||
_userFeedback.participantDecided(lotroGameParticipant);
|
||||
awaitingDecision.decisionMade(answer);
|
||||
|
||||
// Decision successfully made, add the time to user clock
|
||||
addTimeSpentOnDecisionToUserClock(lotroGameParticipant);
|
||||
|
||||
_lotroGame.carryOutPendingActionsUntilDecisionNeeded();
|
||||
startClocksForUsersPendingDecision();
|
||||
|
||||
} catch (DecisionResultInvalidException decisionResultInvalidException) {
|
||||
// Participant provided wrong answer - send a warning message, and ask again for the same decision
|
||||
// _userCommunication.sendWarning(lotroGameParticipant, decisionResultInvalidException.getWarningMessage());
|
||||
@@ -88,6 +98,28 @@ public class LotroGameMediator {
|
||||
}
|
||||
}
|
||||
|
||||
private void startClocksForUsersPendingDecision() {
|
||||
long currentTime = System.currentTimeMillis();
|
||||
Set<String> users = _userFeedback.getUsersPendingDecision();
|
||||
for (String user : users)
|
||||
_decisionQuerySentTimes.put(user, currentTime);
|
||||
}
|
||||
|
||||
private void addTimeSpentOnDecisionToUserClock(String participantId) {
|
||||
long queryTime = _decisionQuerySentTimes.remove(participantId);
|
||||
long currentTime = System.currentTimeMillis();
|
||||
long diffSec = (currentTime - queryTime) / 1000;
|
||||
_playerClocks.put(participantId, _playerClocks.get(participantId) + (int) diffSec);
|
||||
}
|
||||
|
||||
private int getCurrentUserPendingTime(String participantId) {
|
||||
if (!_decisionQuerySentTimes.containsKey(participantId))
|
||||
return 0;
|
||||
long queryTime = _decisionQuerySentTimes.get(participantId);
|
||||
long currentTime = System.currentTimeMillis();
|
||||
return (int) ((currentTime - queryTime) / 1000);
|
||||
}
|
||||
|
||||
public synchronized void processCommunicationChannel(String participantId, ParticipantCommunicationVisitor visitor) {
|
||||
GatheringParticipantCommunicationChannel communicationChannel = _communicationChannels.get(participantId);
|
||||
if (communicationChannel != null)
|
||||
@@ -99,6 +131,13 @@ public class LotroGameMediator {
|
||||
AwaitingDecision awaitingDecision = _userFeedback.getAwaitingDecision(participantId);
|
||||
if (awaitingDecision != null)
|
||||
visitor.visitAwaitingDecision(_lotroGame.getActionStack().getTopmostAction(), awaitingDecision);
|
||||
|
||||
Map<String, Integer> secondsLeft = new HashMap<String, Integer>();
|
||||
for (Map.Entry<String, Integer> playerClock : _playerClocks.entrySet()) {
|
||||
String player = playerClock.getKey();
|
||||
secondsLeft.put(player, _maxSecondsPerPlayer - playerClock.getValue() - getCurrentUserPendingTime(player));
|
||||
}
|
||||
visitor.visitClock(secondsLeft);
|
||||
}
|
||||
|
||||
public synchronized void singupUserForGame(String participantId, ParticipantCommunicationVisitor visitor) {
|
||||
@@ -116,5 +155,10 @@ public class LotroGameMediator {
|
||||
AwaitingDecision awaitingDecision = _userFeedback.getAwaitingDecision(participantId);
|
||||
if (awaitingDecision != null)
|
||||
visitor.visitAwaitingDecision(_lotroGame.getActionStack().getTopmostAction(), awaitingDecision);
|
||||
|
||||
Map<String, Integer> secondsLeft = new HashMap<String, Integer>();
|
||||
for (Map.Entry<String, Integer> playerClock : _playerClocks.entrySet())
|
||||
secondsLeft.put(playerClock.getKey(), _maxSecondsPerPlayer - playerClock.getValue());
|
||||
visitor.visitClock(secondsLeft);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,13 +14,17 @@ import com.gempukku.lotro.logic.vo.LotroDeck;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class LotroServer {
|
||||
private static final Logger log = Logger.getLogger(LotroServer.class);
|
||||
|
||||
private LotroCardBlueprintLibrary _lotroCardBlueprintLibrary = new LotroCardBlueprintLibrary();
|
||||
|
||||
private Map<String, LotroGameMediator> _runningGames = new HashMap<String, LotroGameMediator>();
|
||||
private Map<String, LotroGameMediator> _runningGames = new ConcurrentHashMap<String, LotroGameMediator>();
|
||||
|
||||
private final Map<String, Date> _finishedGamesTime = new LinkedHashMap<String, Date>();
|
||||
private final long _timeToGameDeath = 1000 * 60 * 5; // 5 minutes
|
||||
|
||||
private boolean _started;
|
||||
private CleaningTask _cleaningTask;
|
||||
@@ -83,21 +87,41 @@ public class LotroServer {
|
||||
}
|
||||
|
||||
public void cleanup() {
|
||||
// TODO
|
||||
long currentTime = System.currentTimeMillis();
|
||||
|
||||
synchronized (_finishedGamesTime) {
|
||||
LinkedHashMap<String, Date> copy = new LinkedHashMap<String, Date>(_finishedGamesTime);
|
||||
for (Map.Entry<String, Date> finishedGame : copy.entrySet()) {
|
||||
if (finishedGame.getValue().getTime() > currentTime + _timeToGameDeath) {
|
||||
String gameId = finishedGame.getKey();
|
||||
_runningGames.remove(gameId);
|
||||
_chatServer.destroyChatRoom(getChatRoomName(gameId));
|
||||
_finishedGamesTime.remove(gameId);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String getChatRoomName(String gameId) {
|
||||
return "Game" + gameId;
|
||||
}
|
||||
|
||||
public synchronized String createNewGame(LotroFormat lotroFormat, LotroGameParticipant[] participants) {
|
||||
if (participants.length < 2)
|
||||
throw new IllegalArgumentException("There has to be at least two players");
|
||||
String gameId = String.valueOf(_nextGameId);
|
||||
final String chatRoomName = "Game" + gameId;
|
||||
final String gameId = String.valueOf(_nextGameId);
|
||||
String chatRoomName = getChatRoomName(gameId);
|
||||
|
||||
_chatServer.createChatRoom(chatRoomName);
|
||||
LotroGameMediator lotroGameMediator = new LotroGameMediator(lotroFormat, participants, _lotroCardBlueprintLibrary,
|
||||
new GameResultListener() {
|
||||
@Override
|
||||
public void gameFinished(String winnerPlayerId, Set<String> loserPlayerIds) {
|
||||
_chatServer.destroyChatRoom(chatRoomName);
|
||||
synchronized (_finishedGamesTime) {
|
||||
_finishedGamesTime.put(gameId, new Date());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -4,7 +4,11 @@ import com.gempukku.lotro.GameEvent;
|
||||
import com.gempukku.lotro.logic.decisions.AwaitingDecision;
|
||||
import com.gempukku.lotro.logic.timing.Action;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public interface ParticipantCommunicationVisitor {
|
||||
public void visitClock(Map<String, Integer> secondsLeft);
|
||||
|
||||
public void visitWarning(String warning);
|
||||
|
||||
public void visitAwaitingDecision(Action currentAction, AwaitingDecision awaitingDecision);
|
||||
|
||||
@@ -420,6 +420,23 @@ public class ServerResource {
|
||||
public void visitAwaitingDecision(Action currentAction, AwaitingDecision awaitingDecision) {
|
||||
_element.appendChild(serializeDecision(_doc, currentAction, awaitingDecision));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitClock(Map<String, Integer> secondsLeft) {
|
||||
_element.appendChild(serializeClocks(_doc, secondsLeft));
|
||||
}
|
||||
}
|
||||
|
||||
private Node serializeClocks(Document doc, Map<String, Integer> secondsLeft) {
|
||||
Element clocks = doc.createElement("clocks");
|
||||
for (Map.Entry<String, Integer> userClock : secondsLeft.entrySet()) {
|
||||
Element clock = doc.createElement("clock");
|
||||
clock.setAttribute("participantId", userClock.getKey());
|
||||
clock.appendChild(doc.createTextNode(userClock.getValue().toString()));
|
||||
clocks.appendChild(clock);
|
||||
}
|
||||
|
||||
return clocks;
|
||||
}
|
||||
|
||||
private Node serializeDecision(Document doc, Action currentAction, AwaitingDecision decision) {
|
||||
|
||||
Reference in New Issue
Block a user