diff --git a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/tournament/AbstractTournament.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/tournament/AbstractTournament.java new file mode 100644 index 000000000..ea56597da --- /dev/null +++ b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/tournament/AbstractTournament.java @@ -0,0 +1,271 @@ +package com.gempukku.lotro.tournament; + +import com.gempukku.lotro.competitive.PlayerStanding; +import com.gempukku.lotro.competitive.StandingsProducer; +import com.gempukku.lotro.db.vo.CollectionType; +import com.gempukku.lotro.game.LotroGameParticipant; +import com.gempukku.lotro.logic.vo.LotroDeck; + +import java.util.*; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +public abstract class AbstractTournament implements Tournament { + protected TournamentService _tournamentService; + private String _tournamentId; + private String _lotroFormat; + private CollectionType _collectionType; + private String _tournamentName; + + private int _currentRound; + private int _ongoingGamesCount; + + private TournamentTask _nextTask; + + private HashSet _allPlayers; + private HashMap _playerDecks; + protected HashSet _playersInContention; + private Set _droppedPlayers = new HashSet(); + + private Map _playerByes = new HashMap(); + private List _tournamentMatches = new ArrayList(); + + private List _playerStandings; + + protected ReadWriteLock _lock = new ReentrantReadWriteLock(); + + public AbstractTournament(TournamentService tournamentService, String tournamentId, String format, + CollectionType collectionType, String tournamentName) { + _tournamentService = tournamentService; + _tournamentId = tournamentId; + _lotroFormat = format; + _collectionType = collectionType; + _tournamentName = tournamentName; + + _playerDecks = new HashMap(_tournamentService.getPlayers(tournamentId)); + _allPlayers = new HashSet(_playerDecks.keySet()); + + _playersInContention = new HashSet(_playerDecks.keySet()); + _playersInContention.removeAll(_tournamentService.getDroppedPlayers(tournamentId)); + + int round = 1; + while (true) { + List matches = _tournamentService.getMatches(tournamentId, round); + if (matches.size() > 0) { + Map gamesToCreate = new HashMap(); + for (TournamentMatch match : matches) { + String winner = match.getWinner(); + if (winner != null) { + if (match.isBye()) { + addPlayerBye(winner); + } else { + _tournamentMatches.add(match); + } + } else { + gamesToCreate.put(match.getPlayerOne(), match.getPlayerTwo()); + } + } + _currentRound++; + if (gamesToCreate.size() > 0) { + _nextTask = new CreateMissingGames(gamesToCreate); + break; + } + } else { + _nextTask = new PairPlayers(); + break; + } + } + } + + @Override + public String getTournamentId() { + return _tournamentId; + } + + @Override + public CollectionType getCollectionType() { + return _collectionType; + } + + @Override + public String getFormat() { + return _lotroFormat; + } + + @Override + public String getTournamentName() { + return _tournamentName; + } + + @Override + public void advanceTournament(TournamentCallback tournamentCallback) { + _lock.writeLock().lock(); + try { + if (_nextTask == null) { + if (_ongoingGamesCount == 0) { + if (isFinished()) + finishTournament(tournamentCallback); + else + _nextTask = new PairPlayers(); + } + } + if (_nextTask != null && _nextTask.getExecuteAfter() < System.currentTimeMillis()) { + TournamentTask task = _nextTask; + _nextTask = null; + task.executeTask(tournamentCallback); + } + } finally { + _lock.writeLock().unlock(); + } + } + + private void addPlayerBye(String player) { + Integer byes = _playerByes.get(player); + if (byes == null) + byes = 0; + _playerByes.put(player, byes + 1); + } + + @Override + public void dropPlayer(String player) { + _lock.writeLock().lock(); + try { + if (_playersInContention.contains(player)) { + if (_droppedPlayers.add(player)) + _tournamentService.dropPlayer(_tournamentId, player); + } + } finally { + _lock.writeLock().unlock(); + } + } + + @Override + public int getCurrentRound() { + return _currentRound; + } + + @Override + public void reportGameFinished(TournamentCallback tournamentCallback, String winner, String loser) { + _lock.writeLock().lock(); + try { + _ongoingGamesCount--; + + _tournamentService.setMatchResult(_tournamentId, _currentRound, winner); + + _tournamentMatches.add(new TournamentMatch(winner, loser, winner, _currentRound)); + _playerStandings = null; + if (_ongoingGamesCount == 0) + processToNextTournamentRoundOrFinish(tournamentCallback); + } finally { + _lock.writeLock().unlock(); + } + } + + private void processToNextTournamentRoundOrFinish(TournamentCallback tournamentCallback) { + if (isFinished()) { + finishTournament(tournamentCallback); + } else { + tournamentCallback.broadcastMessage("Tournament " + _tournamentName + " round has finished, next round will start in 2 minutes"); + _nextTask = new PairPlayers(); + } + } + + private void finishTournament(TournamentCallback tournamentCallback) { + tournamentCallback.broadcastMessage("Tournament " + _tournamentName + " is finished"); + awardPrizes(); + } + + private void awardPrizes() { + + } + + @Override + public boolean isPlayerCompeting(String player) { + _lock.readLock().lock(); + try { + return _playersInContention.contains(player); + } finally { + _lock.readLock().unlock(); + } + } + + @Override + public List getCurrentStandings() { + List standings = _playerStandings; + if (standings != null) + return standings; + + _lock.readLock().lock(); + try { + _playerStandings = StandingsProducer.produceStandings(_allPlayers, _tournamentMatches, 1, 0, _playerByes); + return _playerStandings; + } finally { + _lock.readLock().unlock(); + } + } + + private void createNewGame(TournamentCallback tournamentCallback, String playerOne, String playerTwo) { + tournamentCallback.createGame(new LotroGameParticipant(playerOne, _playerDecks.get(playerOne)), + new LotroGameParticipant(playerTwo, _playerDecks.get(playerTwo))); + } + + private class PairPlayers implements TournamentTask { + private long _taskStart = System.currentTimeMillis() + 1000 * 60 * 2; + + @Override + public void executeTask(TournamentCallback tournamentCallback) { + _playersInContention.removeAll(_droppedPlayers); + _droppedPlayers.clear(); + + if (isFinished()) { + finishTournament(tournamentCallback); + } else { + _currentRound++; + pairPlayers(tournamentCallback); + } + } + + @Override + public long getExecuteAfter() { + return _taskStart; + } + } + + protected abstract void pairPlayers(TournamentCallback tournamentCallback); + + protected void pairNewGame(TournamentCallback tournamentCallback, String playerOne, String playerTwo) { + _ongoingGamesCount++; + _tournamentService.addMatch(_tournamentId, _currentRound, playerOne, playerTwo); + createNewGame(tournamentCallback, playerOne, playerTwo); + } + + protected void awardNewBye(TournamentCallback tournamentCallback, String player) { + addPlayerBye(player); + _tournamentService.addMatch(_tournamentId, _currentRound, player, "Bye"); + _tournamentService.setMatchResult(_tournamentId, _currentRound, player); + tournamentCallback.broadcastMessage("Player " + player + " has received a bye"); + } + + private class CreateMissingGames implements TournamentTask { + private Map _gamesToCreate; + + public CreateMissingGames(Map gamesToCreate) { + _gamesToCreate = gamesToCreate; + } + + @Override + public void executeTask(TournamentCallback tournamentCallback) { + for (Map.Entry pairings : _gamesToCreate.entrySet()) { + String playerOne = pairings.getKey(); + String playerTwo = pairings.getValue(); + _ongoingGamesCount++; + createNewGame(tournamentCallback, playerOne, playerTwo); + } + } + + @Override + public long getExecuteAfter() { + return 0; + } + } +} diff --git a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/tournament/SingleEliminationTournament.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/tournament/SingleEliminationTournament.java index 68d7b33d6..78d0516d1 100644 --- a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/tournament/SingleEliminationTournament.java +++ b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/tournament/SingleEliminationTournament.java @@ -1,195 +1,53 @@ package com.gempukku.lotro.tournament; -import com.gempukku.lotro.competitive.PlayerStanding; -import com.gempukku.lotro.competitive.StandingsProducer; import com.gempukku.lotro.db.vo.CollectionType; -import com.gempukku.lotro.game.LotroGameParticipant; -import com.gempukku.lotro.logic.vo.LotroDeck; -import java.util.*; -import java.util.concurrent.locks.ReadWriteLock; -import java.util.concurrent.locks.ReentrantReadWriteLock; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; -public class SingleEliminationTournament implements Tournament { - private CollectionType _collectionType; - private String _lotroFormat; - private String _tournamentName; - private Map _playerDecks; - private TournamentService _tournamentService; - private String _tournamentId; - - private Set _allPlayers; - private Set _playersInContention; - private Set _droppedPlayers = new HashSet(); - private int _currentRound; - - private int _ongoingGamesCount; - - private TournamentTask _nextTask; - - private ReadWriteLock _lock = new ReentrantReadWriteLock(); - - private Map _playerByes = new HashMap(); - - private List _playerStandings; - - private List _tournamentMatches = new ArrayList(); +public class SingleEliminationTournament extends AbstractTournament { + private static String param(String parameters, int index) { + return parameters.split(",")[index]; + } public SingleEliminationTournament(TournamentService tournamentService, String tournamentId, String parameters) { - _tournamentService = tournamentService; + super(tournamentService, tournamentId, + param(parameters, 0), + new CollectionType(param(parameters, 1), param(parameters, 2)), + param(parameters, 3)); + } - String[] params = parameters.split(","); - _lotroFormat = params[0]; - _collectionType = new CollectionType(params[1], params[2]); - _tournamentName = params[3]; + @Override + protected void pairPlayers(TournamentCallback tournamentCallback) { + List playersRandomized = new ArrayList(_playersInContention); + Collections.shuffle(playersRandomized); - _tournamentId = tournamentId; - _playerDecks = new HashMap(_tournamentService.getPlayers(tournamentId)); - - _allPlayers = new HashSet(_playerDecks.keySet()); - - _playersInContention = new HashSet(_playerDecks.keySet()); - _playersInContention.removeAll(_tournamentService.getDroppedPlayers(tournamentId)); - - int round = 1; - while (true) { - List matches = _tournamentService.getMatches(tournamentId, round); - if (matches.size() > 0) { - Map gamesToCreate = new HashMap(); - for (TournamentMatch match : matches) { - String winner = match.getWinner(); - if (winner != null) { - if (match.isBye()) { - addPlayerBye(winner); - } else { - _tournamentMatches.add(match); - } - } else { - gamesToCreate.put(match.getPlayerOne(), match.getPlayerTwo()); - } - } - _currentRound++; - if (gamesToCreate.size() > 0) { - _nextTask = new CreateMissingGames(gamesToCreate); - break; - } + Iterator playerIterator = playersRandomized.iterator(); + while (playerIterator.hasNext()) { + String playerOne = playerIterator.next(); + if (playerIterator.hasNext()) { + String playerTwo = playerIterator.next(); + pairNewGame(tournamentCallback, playerOne, playerTwo); } else { - _nextTask = new PairPlayers(); - break; + awardNewBye(tournamentCallback, playerOne); } } } - @Override - public String getTournamentId() { - return _tournamentId; - } - - @Override - public CollectionType getCollectionType() { - return _collectionType; - } - - @Override - public String getFormat() { - return _lotroFormat; - } - - @Override - public String getTournamentName() { - return _tournamentName; - } - - @Override - public List getCurrentStandings() { - List standings = _playerStandings; - if (standings != null) - return standings; - - _lock.readLock().lock(); - try { - _playerStandings = StandingsProducer.produceStandings(_allPlayers, _tournamentMatches, 1, 0, _playerByes); - return _playerStandings; - } finally { - _lock.readLock().unlock(); - } - } - - @Override - public int getCurrentRound() { - return _currentRound; - } - - @Override - public void advanceTournament(TournamentCallback tournamentCallback) { - _lock.writeLock().lock(); - try { - if (_nextTask == null) { - if (_ongoingGamesCount == 0) { - if (_playersInContention.size() > 1) - _nextTask = new PairPlayers(); - else - finishTournament(tournamentCallback); - } - } - if (_nextTask != null && _nextTask.getExecuteAfter() < System.currentTimeMillis()) { - TournamentTask task = _nextTask; - _nextTask = null; - task.executeTask(tournamentCallback); - } - } finally { - _lock.writeLock().unlock(); - } - } - - @Override - public void dropPlayer(String player) { - _lock.writeLock().lock(); - try { - if (_playersInContention.contains(player)) - _droppedPlayers.add(player); - } finally { - _lock.writeLock().unlock(); - } - } - @Override public void reportGameFinished(TournamentCallback tournamentCallback, String winner, String loser) { _lock.writeLock().lock(); try { - _ongoingGamesCount--; - - _tournamentService.dropPlayer(_tournamentId, loser); - _tournamentService.setMatchResult(_tournamentId, _currentRound, winner); - + dropPlayer(loser); _playersInContention.remove(loser); - _tournamentMatches.add(new TournamentMatch(winner, loser, winner, _currentRound)); - _playerStandings = null; - if (_ongoingGamesCount == 0) - processToNextTournamentRoundOrFinish(tournamentCallback); + super.reportGameFinished(tournamentCallback, winner, loser); } finally { _lock.writeLock().unlock(); } } - private void processToNextTournamentRoundOrFinish(TournamentCallback tournamentCallback) { - if (_playersInContention.size() > 1) { - tournamentCallback.broadcastMessage("Tournament " + _tournamentName + " round has finished, next round will start in 2 minutes"); - _nextTask = new PairPlayers(); - } else { - finishTournament(tournamentCallback); - } - } - - private void finishTournament(TournamentCallback tournamentCallback) { - tournamentCallback.broadcastMessage("Tournament " + _tournamentName + " is finished"); - awardPrizes(); - } - - private void awardPrizes() { - - } - @Override public boolean isFinished() { _lock.readLock().lock(); @@ -199,89 +57,4 @@ public class SingleEliminationTournament implements Tournament { _lock.readLock().unlock(); } } - - @Override - public boolean isPlayerCompeting(String player) { - _lock.readLock().lock(); - try { - return _playersInContention.contains(player); - } finally { - _lock.readLock().unlock(); - } - } - - private class PairPlayers implements TournamentTask { - private long _taskStart = System.currentTimeMillis() + 1000 * 60 * 2; - - @Override - public void executeTask(TournamentCallback tournamentCallback) { - for (String droppedPlayer : _droppedPlayers) - _playersInContention.remove(droppedPlayer); - _droppedPlayers.clear(); - - List playersRandomized = new ArrayList(_playersInContention); - Collections.shuffle(playersRandomized); - if (playersRandomized.size() > 1) { - _currentRound++; - Iterator playerIterator = playersRandomized.iterator(); - while (playerIterator.hasNext()) { - String playerOne = playerIterator.next(); - if (playerIterator.hasNext()) { - String playerTwo = playerIterator.next(); - _ongoingGamesCount++; - _tournamentService.addMatch(_tournamentId, _currentRound, playerOne, playerTwo); - createNewGame(tournamentCallback, playerOne, playerTwo); - } else { - Integer byes = addPlayerBye(playerOne); - _playerByes.put(playerOne, byes + 1); - _tournamentService.addMatch(_tournamentId, _currentRound, playerOne, "Bye"); - _tournamentService.setMatchResult(_tournamentId, _currentRound, playerOne); - tournamentCallback.broadcastMessage("Player " + playerOne + " has received a bye"); - } - } - } else { - finishTournament(tournamentCallback); - } - } - - @Override - public long getExecuteAfter() { - return _taskStart; - } - } - - private void createNewGame(TournamentCallback tournamentCallback, String playerOne, String playerTwo) { - tournamentCallback.createGame(new LotroGameParticipant(playerOne, _playerDecks.get(playerOne)), - new LotroGameParticipant(playerTwo, _playerDecks.get(playerTwo))); - } - - private Integer addPlayerBye(String player) { - Integer byes = _playerByes.get(player); - if (byes == null) - byes = 0; - return byes; - } - - private class CreateMissingGames implements TournamentTask { - private Map _gamesToCreate; - - public CreateMissingGames(Map gamesToCreate) { - _gamesToCreate = gamesToCreate; - } - - @Override - public void executeTask(TournamentCallback tournamentCallback) { - for (Map.Entry pairings : _gamesToCreate.entrySet()) { - String playerOne = pairings.getKey(); - String playerTwo = pairings.getValue(); - _ongoingGamesCount++; - createNewGame(tournamentCallback, playerOne, playerTwo); - } - } - - @Override - public long getExecuteAfter() { - return 0; - } - } }