diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/DefaultLotroGame.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/DefaultLotroGame.java index cac0a4f1c..dea4c91e6 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/DefaultLotroGame.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/DefaultLotroGame.java @@ -36,7 +36,6 @@ public class DefaultLotroGame implements LotroGame { private Set _allPlayers; private String _winnerPlayerId; - private String _winReason; private Map _losers = new HashMap(); private Set _gameResultListeners = new HashSet(); @@ -107,15 +106,25 @@ public class DefaultLotroGame implements LotroGame { @Override public void playerWon(String playerId, String reason) { - _winnerPlayerId = playerId; - _winReason = reason; + // Any remaining players have lost + Set losers = new HashSet(_allPlayers); + losers.removeAll(losers); + losers.remove(playerId); + + for (String loser : losers) + _losers.put(loser, "Other player won"); + + gameWon(playerId, reason); + } + + private void gameWon(String winner, String reason) { + _winnerPlayerId = winner; + if (_gameState != null) _gameState.sendMessage(_winnerPlayerId + " is the winner due to: " + reason); - for (GameResultListener gameResultListener : _gameResultListeners) { - Set losers = new HashSet(_allPlayers); - losers.remove(_winnerPlayerId); - gameResultListener.gameFinished(_winnerPlayerId, losers, reason); - } + + for (GameResultListener gameResultListener : _gameResultListeners) + gameResultListener.gameFinished(_winnerPlayerId, reason, _losers); } @Override @@ -129,7 +138,7 @@ public class DefaultLotroGame implements LotroGame { if (_losers.size() + 1 == _allPlayers.size()) { List allPlayers = new LinkedList(_allPlayers); allPlayers.removeAll(_losers.keySet()); - playerWon(allPlayers.get(0), "Last remaining player in game"); + gameWon(allPlayers.get(0), "Last remaining player in game"); } } } diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/GameResultListener.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/GameResultListener.java index 37c71869d..5131a82f4 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/GameResultListener.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/GameResultListener.java @@ -1,7 +1,7 @@ package com.gempukku.lotro.logic.timing; -import java.util.Set; +import java.util.Map; public interface GameResultListener { - public void gameFinished(String winnerPlayerId, Set loserPlayerIds, String reason); + public void gameFinished(String winnerPlayerId, String winReason, Map loserPlayerIdsWithReasons); } diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/processes/turn/RegroupGameProcess.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/processes/turn/RegroupGameProcess.java index a1811a7c4..d691289fd 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/processes/turn/RegroupGameProcess.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/processes/turn/RegroupGameProcess.java @@ -41,7 +41,7 @@ public class RegroupGameProcess implements GameProcess { public void process() { if (_game.getGameState().getCurrentSiteNumber() == 9 && _game.getModifiersQuerying().hasFlagActive(ModifierFlag.WIN_CHECK_AFTER_SHADOW_RECONCILE)) { - _game.playerWon(_game.getGameState().getCurrentPlayerId(), "Surviving to Regroup phase on site 9"); + _game.playerWon(_game.getGameState().getCurrentPlayerId(), "Surviving to Shadow Reconcile on site 9"); } } diff --git a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/GameHistoryDAO.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/GameHistoryDAO.java new file mode 100644 index 000000000..0f9ad2b14 --- /dev/null +++ b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/GameHistoryDAO.java @@ -0,0 +1,116 @@ +package com.gempukku.lotro.db; + +import com.gempukku.lotro.db.vo.GameHistoryEntry; +import com.gempukku.lotro.db.vo.Player; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Date; +import java.util.LinkedList; +import java.util.List; + +public class GameHistoryDAO { + private DbAccess _dbAccess; + + public GameHistoryDAO(DbAccess dbAccess) { + _dbAccess = dbAccess; + } + + public void addGameHistory(String winner, String loser, String winReason, String loseReason, String winRecordingId, String loseRecordingId, Date startDate, Date endDate) { + try { + Connection connection = _dbAccess.getDataSource().getConnection(); + try { + PreparedStatement statement = connection.prepareStatement("insert into game_history (winner, loser, win_reason, lose_reason, win_recording_id, lose_recording_id, start_date, end_date) values (?,?,?,?,?,?,?,?)"); + try { + statement.setString(1, winner); + statement.setString(2, loser); + statement.setString(3, winReason); + statement.setString(4, loseReason); + statement.setString(5, winRecordingId); + statement.setString(6, loseRecordingId); + statement.setLong(7, startDate.getTime()); + statement.setLong(8, endDate.getTime()); + + statement.execute(); + } finally { + statement.close(); + } + } finally { + connection.close(); + } + } catch (SQLException exp) { + throw new RuntimeException("Unable to get count of player games", exp); + } + } + + public List getGameHistoryForPlayer(Player player, int start, int count) { + try { + Connection connection = _dbAccess.getDataSource().getConnection(); + try { + PreparedStatement statement = connection.prepareStatement("select winner, loser, win_reason, lose_reason, win_recording_id, lose_recording_id, start_date, end_date from game_history where winner=? or loser=? order by end_date deck limit ?, ?"); + try { + statement.setString(1, player.getName()); + statement.setString(2, player.getName()); + statement.setInt(3, start); + statement.setInt(4, count); + ResultSet rs = statement.executeQuery(); + try { + List result = new LinkedList(); + while (rs.next()) { + String winner = rs.getString(1); + String loser = rs.getString(2); + String winReason = rs.getString(3); + String loseReason = rs.getString(4); + String winRecordingId = rs.getString(5); + String loseRecordingId = rs.getString(6); + Date startDate = new Date(rs.getLong(7)); + Date endDate = new Date(rs.getLong(8)); + + GameHistoryEntry entry = new GameHistoryEntry(winner, winReason, winRecordingId, loser, loseReason, loseRecordingId, startDate, endDate); + result.add(entry); + } + return result; + } finally { + rs.close(); + } + } finally { + statement.close(); + } + } finally { + connection.close(); + } + } catch (SQLException exp) { + throw new RuntimeException("Unable to get count of player games", exp); + } + } + + public int getGameHistoryForPlayerCount(Player player) { + try { + Connection connection = _dbAccess.getDataSource().getConnection(); + try { + PreparedStatement statement = connection.prepareStatement("select count(*) from game_history where winner=? or loser=?"); + try { + statement.setString(1, player.getName()); + statement.setString(2, player.getName()); + ResultSet rs = statement.executeQuery(); + try { + if (rs.next()) + return rs.getInt(1); + else + return -1; + } finally { + rs.close(); + } + } finally { + statement.close(); + } + } finally { + connection.close(); + } + } catch (SQLException exp) { + throw new RuntimeException("Unable to get count of player games", exp); + } + } +} diff --git a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/vo/GameHistoryEntry.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/vo/GameHistoryEntry.java new file mode 100644 index 000000000..2677e268d --- /dev/null +++ b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/vo/GameHistoryEntry.java @@ -0,0 +1,60 @@ +package com.gempukku.lotro.db.vo; + +import java.util.Date; + +public class GameHistoryEntry { + private String _winner; + private String _loser; + + private String _winReason; + private String _loseReason; + + private String _winnerRecording; + private String _loserRecording; + + private Date _startTime; + private Date _endTime; + + public GameHistoryEntry(String winner, String winReason, String winnerRecording, String loser, String loseReason, String loserRecording, Date startTime, Date endTime) { + _winner = winner; + _winReason = winReason; + _winnerRecording = winnerRecording; + _loser = loser; + _loseReason = loseReason; + _loserRecording = loserRecording; + _startTime = startTime; + _endTime = endTime; + } + + public String getLoser() { + return _loser; + } + + public String getLoseReason() { + return _loseReason; + } + + public String getLoserRecording() { + return _loserRecording; + } + + public String getWinner() { + return _winner; + } + + public String getWinnerRecording() { + return _winnerRecording; + } + + public String getWinReason() { + return _winReason; + } + + public Date getEndTime() { + return _endTime; + } + + public Date getStartTime() { + return _startTime; + } +} diff --git a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/GameRecorder.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/GameRecorder.java new file mode 100644 index 000000000..5dcb777ae --- /dev/null +++ b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/GameRecorder.java @@ -0,0 +1,123 @@ +package com.gempukku.lotro.game; + +import com.gempukku.lotro.db.GameHistoryDAO; +import com.gempukku.lotro.game.state.EventSerializer; +import com.gempukku.lotro.game.state.GameEvent; +import com.gempukku.lotro.game.state.GatheringParticipantCommunicationChannel; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.transform.Result; +import javax.xml.transform.Source; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.*; + +public class GameRecorder { + private static String _possibleChars = "abcdefghijklmnopqrstuvwxyz0123456789"; + private static int _charsCount = _possibleChars.length(); + + private GameHistoryDAO _gameHistoryDao; + + public GameRecorder(GameHistoryDAO gameHistoryDao) { + _gameHistoryDao = gameHistoryDao; + } + + private String randomUid() { + int length = 16; + char[] chars = new char[length]; + Random rnd = new Random(); + for (int i = 0; i < length; i++) + chars[i] = _possibleChars.charAt(rnd.nextInt(_charsCount)); + + return new String(chars); + } + + public InputStream getRecordedGame(String playerId, String gameId) throws IOException { + final File file = getRecordingFile(playerId, gameId); + if (!file.exists() || !file.isFile()) + return null; + return new FileInputStream(file); + } + + public GameRecordingInProgress recordGame(LotroGameMediator lotroGame) { + final Date startData = new Date(); + final Map recordingChannels = new HashMap(); + for (String playerId : lotroGame.getPlayersPlaying()) { + GatheringParticipantCommunicationChannel recordChannel = new GatheringParticipantCommunicationChannel(playerId); + lotroGame.addGameStateListener(playerId, recordChannel); + recordingChannels.put(playerId, recordChannel); + } + + return new GameRecordingInProgress() { + @Override + public void finishRecording(String winner, String winReason, String loser, String loseReason) { + Map playerRecordingId = saveRecordedChannels(recordingChannels); + _gameHistoryDao.addGameHistory(winner, loser, winReason, loseReason, playerRecordingId.get(winner), playerRecordingId.get(loser), startData, new Date()); + } + }; + } + + public interface GameRecordingInProgress { + public void finishRecording(String winner, String winReason, String loser, String loseReason); + } + + private File getRecordingFile(String playerId, String gameId) { + File gameReplayFolder = new File("i:\\gemp-lotr\\replay"); + File playerReplayFolder = new File(gameReplayFolder, playerId); + return new File(playerReplayFolder, gameId + ".xml"); + } + + private Map saveRecordedChannels(Map gameProgress) { + Map result = new HashMap(); + for (Map.Entry playerRecordings : gameProgress.entrySet()) { + String playerId = playerRecordings.getKey(); + + File replayFile; + String gameRecordingId; + do { + gameRecordingId = randomUid(); + replayFile = getRecordingFile(playerId, gameRecordingId); + } while (replayFile.exists()); + + replayFile.getParentFile().mkdirs(); + + final List gameEvents = playerRecordings.getValue().consumeGameEvents(); + + try { + DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder(); + Document doc = documentBuilder.newDocument(); + Element gameReplay = doc.createElement("gameReplay"); + EventSerializer serializer = new EventSerializer(); + for (GameEvent gameEvent : gameEvents) { + gameReplay.appendChild(serializer.serializeEvent(doc, gameEvent)); + } + + doc.appendChild(gameReplay); + + // Prepare the DOM document for writing + Source source = new DOMSource(doc); + + // Prepare the output file + Result streamResult = new StreamResult(replayFile); + + // Write the DOM document to the file + Transformer xformer = TransformerFactory.newInstance().newTransformer(); + xformer.transform(source, streamResult); + } catch (Exception exp) { + + } + result.put(playerId, gameRecordingId); + } + return result; + } +} diff --git a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/GameRecording.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/GameRecording.java deleted file mode 100644 index 693e8fd77..000000000 --- a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/GameRecording.java +++ /dev/null @@ -1,85 +0,0 @@ -package com.gempukku.lotro.game; - -import com.gempukku.lotro.game.state.EventSerializer; -import com.gempukku.lotro.game.state.GameEvent; -import com.gempukku.lotro.game.state.GatheringParticipantCommunicationChannel; -import com.gempukku.lotro.logic.timing.GameResultListener; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.transform.Result; -import javax.xml.transform.Source; -import javax.xml.transform.Transformer; -import javax.xml.transform.TransformerFactory; -import javax.xml.transform.dom.DOMSource; -import javax.xml.transform.stream.StreamResult; -import java.io.File; -import java.util.List; -import java.util.Map; -import java.util.Random; -import java.util.Set; - -public class GameRecording implements GameResultListener { - private Map _gameProgress; - - private static String _possibleChars = "abcdefghijklmnopqrstuvwxyz0123456789"; - private static int _charsCount = _possibleChars.length(); - - public GameRecording(Map gameProgress) { - _gameProgress = gameProgress; - } - - private String randomUid() { - int length = 16; - char[] chars = new char[length]; - Random rnd = new Random(); - for (int i = 0; i < length; i++) - chars[i] = _possibleChars.charAt(rnd.nextInt(_charsCount)); - - return new String(chars); - } - - @Override - public void gameFinished(String winnerPlayerId, Set loserPlayerIds, String reason) { - File gameReplayFolder = new File("i:\\gemp-lotr\\replay"); - gameReplayFolder.mkdirs(); - for (Map.Entry playerRecordings : _gameProgress.entrySet()) { - String playerId = playerRecordings.getKey(); - File playerReplayFolder = new File(gameReplayFolder, playerId); - playerReplayFolder.mkdir(); - File replayFile; - do { - replayFile = new File(playerReplayFolder, randomUid() + ".xml"); - } while (replayFile.exists()); - - final List gameEvents = playerRecordings.getValue().consumeGameEvents(); - - try { - DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); - DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder(); - Document doc = documentBuilder.newDocument(); - Element gameReplay = doc.createElement("gameReplay"); - EventSerializer serializer = new EventSerializer(); - for (GameEvent gameEvent : gameEvents) { - gameReplay.appendChild(serializer.serializeEvent(doc, gameEvent)); - } - - doc.appendChild(gameReplay); - - // Prepare the DOM document for writing - Source source = new DOMSource(doc); - - // Prepare the output file - Result result = new StreamResult(replayFile); - - // Write the DOM document to the file - Transformer xformer = TransformerFactory.newInstance().newTransformer(); - xformer.transform(source, result); - } catch (Exception exp) { - - } - } - } -} diff --git a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/LotroGameMediator.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/LotroGameMediator.java index 57e610618..13cabaa07 100644 --- a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/LotroGameMediator.java +++ b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/LotroGameMediator.java @@ -3,6 +3,7 @@ package com.gempukku.lotro.game; import com.gempukku.lotro.common.Keyword; import com.gempukku.lotro.common.Phase; import com.gempukku.lotro.common.Zone; +import com.gempukku.lotro.communication.GameStateListener; import com.gempukku.lotro.game.state.GameEvent; import com.gempukku.lotro.game.state.GatheringParticipantCommunicationChannel; import com.gempukku.lotro.logic.decisions.AwaitingDecision; @@ -46,16 +47,14 @@ public class LotroGameMediator { } _lotroGame = new DefaultLotroGame(lotroFormat, decks, _userFeedback, library); + } - final HashMap recordingChannels = new HashMap(); - for (String playerId : _playersPlaying) { - final GatheringParticipantCommunicationChannel playerRecording = new GatheringParticipantCommunicationChannel(playerId); - _lotroGame.addGameStateListener(playerId, playerRecording); - recordingChannels.put(playerId, playerRecording); - } + public void addGameStateListener(String playerId, GameStateListener listener) { + _lotroGame.addGameStateListener(playerId, listener); + } - _lotroGame.addGameResultListener( - new GameRecording(recordingChannels)); + public void removeGameStateListener(GameStateListener listener) { + _lotroGame.removeGameStateListener(listener); } public void addGameResultListener(GameResultListener listener) { diff --git a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/LotroServer.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/LotroServer.java index a5df4462d..496480efb 100644 --- a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/LotroServer.java +++ b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/LotroServer.java @@ -7,12 +7,16 @@ import com.gempukku.lotro.common.CardType; import com.gempukku.lotro.common.Keyword; import com.gempukku.lotro.db.DbAccess; import com.gempukku.lotro.db.DeckDAO; +import com.gempukku.lotro.db.GameHistoryDAO; import com.gempukku.lotro.db.PlayerDAO; +import com.gempukku.lotro.db.vo.GameHistoryEntry; import com.gempukku.lotro.db.vo.Player; import com.gempukku.lotro.logic.timing.GameResultListener; import com.gempukku.lotro.logic.vo.LotroDeck; import org.apache.log4j.Logger; +import java.io.IOException; +import java.io.InputStream; import java.util.*; import java.util.concurrent.ConcurrentHashMap; @@ -30,8 +34,10 @@ public class LotroServer extends AbstractServer { private PlayerDAO _playerDao; private DeckDAO _deckDao; + private GameHistoryDAO _gameHistoryDao; private DefaultCardCollection _defaultCollection; private ChatServer _chatServer; + private GameRecorder _gameRecorder; public LotroServer(DbAccess dbAccess, LotroCardBlueprintLibrary library, ChatServer chatServer, boolean test) { _lotroCardBlueprintLibrary = library; @@ -55,6 +61,22 @@ public class LotroServer extends AbstractServer { _playerDao = new PlayerDAO(dbAccess); _deckDao = new DeckDAO(dbAccess); + + _gameHistoryDao = new GameHistoryDAO(dbAccess); + + _gameRecorder = new GameRecorder(_gameHistoryDao); + } + + public InputStream getGameRecording(String playerId, String gameId) throws IOException { + return _gameRecorder.getRecordedGame(playerId, gameId); + } + + public List getPlayerGameHistory(Player player, int start, int count) { + return _gameHistoryDao.getGameHistoryForPlayer(player, start, count); + } + + public int getPlayerGameHistoryRecordCount(Player player) { + return _gameHistoryDao.getGameHistoryForPlayerCount(player); } public LotroCardBlueprintLibrary getLotroCardBlueprintLibrary() { @@ -112,13 +134,24 @@ public class LotroServer extends AbstractServer { lotroGameMediator.addGameResultListener( new GameResultListener() { @Override - public void gameFinished(String winnerPlayerId, Set loserPlayerIds, String reason) { - log.debug("Game finished, winner is - " + winnerPlayerId + " due to: " + reason); + public void gameFinished(String winnerPlayerId, String winReason, Map loserPlayerIdsWithReasons) { + log.debug("Game finished, winner is - " + winnerPlayerId + " due to: " + winReason); synchronized (_finishedGamesTime) { _finishedGamesTime.put(gameId, new Date()); } } }); + final GameRecorder.GameRecordingInProgress gameRecordingInProgress = _gameRecorder.recordGame(lotroGameMediator); + lotroGameMediator.addGameResultListener( + new GameResultListener() { + @Override + public void gameFinished(String winnerPlayerId, String winReason, Map loserPlayerIdsWithReasons) { + final Map.Entry loserEntry = loserPlayerIdsWithReasons.entrySet().iterator().next(); + + gameRecordingInProgress.finishRecording(winnerPlayerId, winReason, loserEntry.getKey(), loserEntry.getValue()); + } + } + ); _runningGames.put(gameId, lotroGameMediator); _nextGameId++; diff --git a/gemp-lotr/gemp-lotr-web/src/main/java/com/gempukku/lotro/server/ServerResource.java b/gemp-lotr/gemp-lotr-web/src/main/java/com/gempukku/lotro/server/ServerResource.java index f8948f9f5..ed155062c 100644 --- a/gemp-lotr/gemp-lotr-web/src/main/java/com/gempukku/lotro/server/ServerResource.java +++ b/gemp-lotr/gemp-lotr-web/src/main/java/com/gempukku/lotro/server/ServerResource.java @@ -8,6 +8,7 @@ import com.gempukku.lotro.db.CollectionDAO; import com.gempukku.lotro.db.DbAccess; import com.gempukku.lotro.db.DeckDAO; import com.gempukku.lotro.db.PlayerDAO; +import com.gempukku.lotro.db.vo.GameHistoryEntry; import com.gempukku.lotro.db.vo.League; import com.gempukku.lotro.db.vo.Player; import com.gempukku.lotro.game.*; @@ -35,7 +36,9 @@ import javax.ws.rs.core.StreamingOutput; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; -import java.io.*; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; import java.util.*; @Singleton @@ -125,36 +128,87 @@ public class ServerResource { @Produces(MediaType.APPLICATION_XML) public StreamingOutput getReplay( @PathParam("replayId") String replayId) throws ParserConfigurationException { - File gameReplayFolder = new File("i:\\gemp-lotr\\replay"); if (!replayId.contains("$")) sendError(Response.Status.NOT_FOUND); if (replayId.contains(".")) sendError(Response.Status.NOT_FOUND); - String[] split = replayId.split("\\$"); + final String[] split = replayId.split("\\$"); if (split.length != 2) sendError(Response.Status.NOT_FOUND); - final File replayFile = new File(new File(gameReplayFolder, split[0]), split[1] + ".xml"); - if (!replayFile.exists() || !replayFile.isFile()) - sendError(Response.Status.NOT_FOUND); - return new StreamingOutput() { @Override public void write(OutputStream outputStream) throws IOException, WebApplicationException { - InputStream is = new FileInputStream(replayFile); + final InputStream recordedGame = _lotroServer.getGameRecording(split[0], split[1]); + if (recordedGame == null) + sendError(Response.Status.NOT_FOUND); try { byte[] bytes = new byte[1024]; int count; - while ((count = is.read(bytes)) != -1) + while ((count = recordedGame.read(bytes)) != -1) outputStream.write(bytes, 0, count); } finally { - is.close(); + recordedGame.close(); } } }; } + @Path("/gameHistory/{playerId}") + @GET + @Produces(MediaType.APPLICATION_XML) + public Document getGameHistory( + @PathParam("playerId") String playerId, + @QueryParam("start") int start, + @QueryParam("count") int count, + @QueryParam("participantId") String participantId, + @Context HttpServletRequest request) throws ParserConfigurationException { + if (!_test) + participantId = getLoggedUser(request); + + if (start < 0 || count < 1 || count > 100) + sendError(Response.Status.BAD_REQUEST); + + PlayerDAO playerDao = _lotroServer.getPlayerDao(); + + Player player = playerDao.getPlayer(participantId); + if (player == null) + sendError(Response.Status.UNAUTHORIZED); + + final List playerGameHistory = _lotroServer.getPlayerGameHistory(player, start, count); + int recordCount = _lotroServer.getPlayerGameHistoryRecordCount(player); + + DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder(); + Document doc = documentBuilder.newDocument(); + Element gameHistory = doc.createElement("gameHistory"); + gameHistory.setAttribute("count", String.valueOf(recordCount)); + gameHistory.setAttribute("playerId", participantId); + + for (GameHistoryEntry gameHistoryEntry : playerGameHistory) { + Element historyEntry = doc.createElement("historyEntry"); + historyEntry.setAttribute("winner", gameHistoryEntry.getWinner()); + historyEntry.setAttribute("loser", gameHistoryEntry.getLoser()); + + historyEntry.setAttribute("winReason", gameHistoryEntry.getWinReason()); + historyEntry.setAttribute("loseReason", gameHistoryEntry.getLoseReason()); + + if (gameHistoryEntry.getWinner().equals(participantId)) + historyEntry.setAttribute("gameRecordingId", gameHistoryEntry.getWinnerRecording()); + else if (gameHistoryEntry.getLoser().equals(participantId)) + historyEntry.setAttribute("gameRecordingId", gameHistoryEntry.getLoserRecording()); + + historyEntry.setAttribute("startTime", String.valueOf(gameHistoryEntry.getStartTime().getTime())); + historyEntry.setAttribute("endTime", String.valueOf(gameHistoryEntry.getEndTime().getTime())); + + gameHistory.appendChild(historyEntry); + } + + doc.appendChild(gameHistory); + return doc; + } + @Path("/game/{gameId}") @GET @Produces(MediaType.APPLICATION_XML) @@ -843,9 +897,7 @@ public class ServerResource { return loggedUser; } - private void sendError(Response.Status status) { - WebApplicationException webApplicationException = new WebApplicationException(status); -// _logger.debug("Sending error to user: " + status.getStatusCode(), webApplicationException); - throw webApplicationException; + private void sendError(Response.Status status) throws WebApplicationException { + throw new WebApplicationException(status); } }