Extracting AbstractTournament.

This commit is contained in:
marcins78@gmail.com
2012-07-03 14:15:26 +00:00
parent cea2d7de85
commit cc109418ed
2 changed files with 297 additions and 253 deletions

View File

@@ -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<String> _allPlayers;
private HashMap<String, LotroDeck> _playerDecks;
protected HashSet<String> _playersInContention;
private Set<String> _droppedPlayers = new HashSet<String>();
private Map<String, Integer> _playerByes = new HashMap<String, Integer>();
private List<TournamentMatch> _tournamentMatches = new ArrayList<TournamentMatch>();
private List<PlayerStanding> _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<String, LotroDeck>(_tournamentService.getPlayers(tournamentId));
_allPlayers = new HashSet<String>(_playerDecks.keySet());
_playersInContention = new HashSet<String>(_playerDecks.keySet());
_playersInContention.removeAll(_tournamentService.getDroppedPlayers(tournamentId));
int round = 1;
while (true) {
List<TournamentMatch> matches = _tournamentService.getMatches(tournamentId, round);
if (matches.size() > 0) {
Map<String, String> gamesToCreate = new HashMap<String, String>();
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<PlayerStanding> getCurrentStandings() {
List<PlayerStanding> 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<String, String> _gamesToCreate;
public CreateMissingGames(Map<String, String> gamesToCreate) {
_gamesToCreate = gamesToCreate;
}
@Override
public void executeTask(TournamentCallback tournamentCallback) {
for (Map.Entry<String, String> pairings : _gamesToCreate.entrySet()) {
String playerOne = pairings.getKey();
String playerTwo = pairings.getValue();
_ongoingGamesCount++;
createNewGame(tournamentCallback, playerOne, playerTwo);
}
}
@Override
public long getExecuteAfter() {
return 0;
}
}
}

View File

@@ -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<String, LotroDeck> _playerDecks;
private TournamentService _tournamentService;
private String _tournamentId;
private Set<String> _allPlayers;
private Set<String> _playersInContention;
private Set<String> _droppedPlayers = new HashSet<String>();
private int _currentRound;
private int _ongoingGamesCount;
private TournamentTask _nextTask;
private ReadWriteLock _lock = new ReentrantReadWriteLock();
private Map<String, Integer> _playerByes = new HashMap<String, Integer>();
private List<PlayerStanding> _playerStandings;
private List<TournamentMatch> _tournamentMatches = new ArrayList<TournamentMatch>();
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<String> playersRandomized = new ArrayList<String>(_playersInContention);
Collections.shuffle(playersRandomized);
_tournamentId = tournamentId;
_playerDecks = new HashMap<String, LotroDeck>(_tournamentService.getPlayers(tournamentId));
_allPlayers = new HashSet<String>(_playerDecks.keySet());
_playersInContention = new HashSet<String>(_playerDecks.keySet());
_playersInContention.removeAll(_tournamentService.getDroppedPlayers(tournamentId));
int round = 1;
while (true) {
List<TournamentMatch> matches = _tournamentService.getMatches(tournamentId, round);
if (matches.size() > 0) {
Map<String, String> gamesToCreate = new HashMap<String, String>();
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<String> 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<PlayerStanding> getCurrentStandings() {
List<PlayerStanding> 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<String> playersRandomized = new ArrayList<String>(_playersInContention);
Collections.shuffle(playersRandomized);
if (playersRandomized.size() > 1) {
_currentRound++;
Iterator<String> 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<String, String> _gamesToCreate;
public CreateMissingGames(Map<String, String> gamesToCreate) {
_gamesToCreate = gamesToCreate;
}
@Override
public void executeTask(TournamentCallback tournamentCallback) {
for (Map.Entry<String, String> pairings : _gamesToCreate.entrySet()) {
String playerOne = pairings.getKey();
String playerTwo = pairings.getValue();
_ongoingGamesCount++;
createNewGame(tournamentCallback, playerOne, playerTwo);
}
}
@Override
public long getExecuteAfter() {
return 0;
}
}
}