From d834011b1557fd80a83943fa2429a9898fb9a592 Mon Sep 17 00:00:00 2001 From: "marcins78@gmail.com" Date: Mon, 30 Jul 2012 14:23:50 +0000 Subject: [PATCH] Work on the server side of drafting. --- .../com/gempukku/lotro/game/LotroFormat.java | 2 +- .../gempukku/lotro/draft/DefaultDraft.java | 228 ++++++++++++++++++ .../java/com/gempukku/lotro/draft/Draft.java | 16 ++ .../gempukku/lotro/draft/DraftCallback.java | 7 + .../com/gempukku/lotro/draft/DraftPack.java | 23 ++ .../game/formats/DefaultLotroFormat.java | 7 +- .../com/gempukku/lotro/hall/HallServer.java | 4 +- .../gempukku/lotro/server/DeckResource.java | 2 +- 8 files changed, 284 insertions(+), 5 deletions(-) create mode 100644 gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/draft/DefaultDraft.java create mode 100644 gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/draft/Draft.java create mode 100644 gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/draft/DraftCallback.java create mode 100644 gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/draft/DraftPack.java diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/LotroFormat.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/LotroFormat.java index 9b42a7d1f..07b09ae9a 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/LotroFormat.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/LotroFormat.java @@ -14,7 +14,7 @@ public interface LotroFormat { public String getName(); - public void validateDeck(Player player, LotroDeck deck) throws DeckInvalidException; + public void validateDeck(LotroDeck deck) throws DeckInvalidException; public List getValidSets(); diff --git a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/draft/DefaultDraft.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/draft/DefaultDraft.java new file mode 100644 index 000000000..0c1319671 --- /dev/null +++ b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/draft/DefaultDraft.java @@ -0,0 +1,228 @@ +package com.gempukku.lotro.draft; + +import com.gempukku.lotro.collection.CollectionsManager; +import com.gempukku.lotro.db.vo.CollectionType; +import com.gempukku.lotro.game.*; +import com.gempukku.lotro.game.formats.LotroFormatLibrary; +import com.gempukku.lotro.logic.vo.LotroDeck; +import com.gempukku.lotro.packs.PacksStorage; +import com.gempukku.lotro.tournament.SingleEliminationTournament; +import com.gempukku.lotro.tournament.Tournament; +import com.gempukku.lotro.tournament.TournamentService; + +import java.util.*; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +public class DefaultDraft implements Draft { + // 45 seconds + public static final int PICK_TIME = 45 * 1000; + // 20 minutes + public static final int DECK_BUILD_TIME = 20 * 60 * 1000; + + private String _tournamentIdPrefix; + private String _tournamentNamePrefix; + private String _tournamentId; + private String _tournamentName; + private LotroFormatLibrary _formatLibrary; + private String _format; + private CollectionsManager _collectionsManager; + private TournamentService _tournamentService; + private CollectionType _collectionType; + private PacksStorage _packsStorage; + private DraftPack _draftPack; + private List _players; + + private List _cardChoices = new ArrayList(); + private Map _cardChoice = new HashMap(); + + private int _playerCount; + private boolean _deckBuildingStarted; + + private long _lastPickStart; + private long _deckBuildStart; + + private int _nextPickNumber = 0; + private int _nextPackIndex = 0; + private Map _playerDecks = new HashMap(); + + private ReadWriteLock _lock = new ReentrantReadWriteLock(); + + public DefaultDraft(String tournamentId, String tournamentName, LotroFormatLibrary formatLibrary, String format, CollectionsManager collectionsManager, TournamentService tournamentService, CollectionType collectionType, PacksStorage packsStorage, DraftPack draftPack, List players) { + _tournamentId = tournamentId; + _tournamentName = tournamentName; + _formatLibrary = formatLibrary; + _format = format; + _collectionsManager = collectionsManager; + _tournamentService = tournamentService; + _collectionType = collectionType; + _packsStorage = packsStorage; + _draftPack = draftPack; + _players = players; + _playerCount = _players.size(); + + CardCollection fixedCollection = _draftPack.getFixedCollection(); + for (Player player : _players) + _collectionsManager.addPlayerCollection(player, _collectionType, fixedCollection); + } + + @Override + public void advanceDraft(DraftCallback draftCallback) { + _lock.writeLock().lock(); + try { + if (_deckBuildingStarted) { + if (haveAllPlayersSubmittedDecks() || deckBuildTimePassed()) { + startTournament(draftCallback); + } + } else { + if (haveAllPlayersPicked()) { + if (haveAllCardsBeenChosen()) { + if (haveMorePacks()) { + openNextPacks(); + } else { + _deckBuildStart = System.currentTimeMillis(); + _deckBuildingStarted = true; + } + } else { + presentNewCardChoices(); + } + } else { + if (choiceTimePassed()) { + forceRandomCardChoice(); + } + } + } + } finally { + _lock.writeLock().unlock(); + } + } + + @Override + public void playerChosenCard(String playerName, String cardId) { + _lock.writeLock().lock(); + try { + playerChosen(playerName, cardId); + } finally { + _lock.writeLock().unlock(); + } + } + + @Override + public CardCollection getCardChoice(String playerName) { + _lock.readLock().lock(); + try { + if (_deckBuildingStarted) + return null; + MutableCardCollection cardChoice = _cardChoice.get(playerName); + if (cardChoice == null) + cardChoice = new DefaultCardCollection(); + + return cardChoice; + } finally { + _lock.readLock().unlock(); + } + } + + @Override + public void playerSummittedDeck(Player player, LotroDeck deck) throws DeckInvalidException { + _lock.writeLock().lock(); + try { + LotroFormat format = _formatLibrary.getFormat(_format); + format.validateDeck(deck); + + CardCollection collection = _collectionsManager.getPlayerCollection(player, _collectionType.getCode()); + if (collection == null) + throw new DeckInvalidException("You don't have cards in the required collection to play in this format"); + + Map deckCardCounts = CollectionUtils.getTotalCardCountForDeck(deck); + + for (Map.Entry cardCount : deckCardCounts.entrySet()) { + final int collectionCount = collection.getItemCount(cardCount.getKey()); + if (collectionCount < cardCount.getValue()) + throw new DeckInvalidException("You don't have the required cards in collection"); + } + + _playerDecks.put(player.getName(), deck); + } finally { + _lock.writeLock().unlock(); + } + } + + private void startTournament(DraftCallback draftCallback) { + String parameters = _format + "," + _collectionType.getCode() + "," + _collectionType.getFullName() + "," + _tournamentName; + + for (Map.Entry playerDeck : _playerDecks.entrySet()) + _tournamentService.addPlayer(_tournamentId, playerDeck.getKey(), playerDeck.getValue()); + + Tournament tournament = _tournamentService.addTournament(_tournamentId, SingleEliminationTournament.class.getName(), parameters, new Date()); + + draftCallback.convertToTournament(tournament); + } + + private boolean haveAllPlayersSubmittedDecks() { + return _playerDecks.size() == _playerCount; + } + + private void forceRandomCardChoice() { + Map cardChoiceCopy = new HashMap(_cardChoice); + + for (Map.Entry playerChoices : cardChoiceCopy.entrySet()) { + String playerName = playerChoices.getKey(); + MutableCardCollection collection = playerChoices.getValue(); + String cardId = collection.getAll().entrySet().iterator().next().getKey(); + playerChosen(playerName, cardId); + } + } + + private void playerChosen(String playerName, String cardId) { + MutableCardCollection cardChoice = _cardChoice.get(playerName); + if (cardChoice != null) { + if (cardChoice.removeItem(cardId, 1)) { + _collectionsManager.addItemsToPlayerCollection(playerName, _collectionType, Arrays.asList(CardCollection.Item.createItem(cardId, 1))); + _cardChoice.remove(playerName); + } + } + } + + private void presentNewCardChoices() { + for (int i = 0; i < _players.size(); i++) { + Player player = _players.get(i); + _cardChoice.put(player.getName(), _cardChoices.get((i + _nextPickNumber) % _playerCount)); + } + _nextPickNumber++; + _lastPickStart = System.currentTimeMillis(); + } + + private void openNextPacks() { + _cardChoices.clear(); + String packId = _draftPack.getPacks().get(_nextPackIndex); + for (int i = 0; i < _playerCount; i++) { + MutableCardCollection cardCollection = new DefaultCardCollection(); + cardCollection.addItem(packId, 1); + cardCollection.openPack(packId, null, _packsStorage); + _cardChoices.add(cardCollection); + } + _nextPackIndex++; + _nextPickNumber = 0; + } + + private boolean deckBuildTimePassed() { + return System.currentTimeMillis() > DECK_BUILD_TIME + _deckBuildStart; + } + + private boolean choiceTimePassed() { + return System.currentTimeMillis() > PICK_TIME + _lastPickStart; + } + + private boolean haveMorePacks() { + return _nextPackIndex < _draftPack.getPacks().size(); + } + + private boolean haveAllCardsBeenChosen() { + return _cardChoices.size() == 0 || _cardChoices.get(0).getAll().size() == 0; + } + + private boolean haveAllPlayersPicked() { + return _cardChoice.isEmpty(); + } +} diff --git a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/draft/Draft.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/draft/Draft.java new file mode 100644 index 000000000..39422daee --- /dev/null +++ b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/draft/Draft.java @@ -0,0 +1,16 @@ +package com.gempukku.lotro.draft; + +import com.gempukku.lotro.game.CardCollection; +import com.gempukku.lotro.game.DeckInvalidException; +import com.gempukku.lotro.game.Player; +import com.gempukku.lotro.logic.vo.LotroDeck; + +public interface Draft { + public void advanceDraft(DraftCallback draftCallback); + + public void playerChosenCard(String playerName, String cardId); + + public void playerSummittedDeck(Player player, LotroDeck deck) throws DeckInvalidException; + + public CardCollection getCardChoice(String playerName); +} diff --git a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/draft/DraftCallback.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/draft/DraftCallback.java new file mode 100644 index 000000000..01c116564 --- /dev/null +++ b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/draft/DraftCallback.java @@ -0,0 +1,7 @@ +package com.gempukku.lotro.draft; + +import com.gempukku.lotro.tournament.Tournament; + +public interface DraftCallback { + public void convertToTournament(Tournament tournament); +} diff --git a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/draft/DraftPack.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/draft/DraftPack.java new file mode 100644 index 000000000..bfdb57283 --- /dev/null +++ b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/draft/DraftPack.java @@ -0,0 +1,23 @@ +package com.gempukku.lotro.draft; + +import com.gempukku.lotro.game.CardCollection; + +import java.util.List; + +public class DraftPack { + public CardCollection _fixedCollection; + public List _packs; + + public DraftPack(CardCollection fixedCollection, List packs) { + _fixedCollection = fixedCollection; + _packs = packs; + } + + public CardCollection getFixedCollection() { + return _fixedCollection; + } + + public List getPacks() { + return _packs; + } +} diff --git a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/formats/DefaultLotroFormat.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/formats/DefaultLotroFormat.java index 7e06dce47..9f17a04e5 100644 --- a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/formats/DefaultLotroFormat.java +++ b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/formats/DefaultLotroFormat.java @@ -4,7 +4,10 @@ import com.gempukku.lotro.common.Block; import com.gempukku.lotro.common.CardType; import com.gempukku.lotro.common.Keyword; import com.gempukku.lotro.common.Side; -import com.gempukku.lotro.game.*; +import com.gempukku.lotro.game.DeckInvalidException; +import com.gempukku.lotro.game.LotroCardBlueprint; +import com.gempukku.lotro.game.LotroCardBlueprintLibrary; +import com.gempukku.lotro.game.LotroFormat; import com.gempukku.lotro.logic.GameUtils; import com.gempukku.lotro.logic.vo.LotroDeck; @@ -113,7 +116,7 @@ public class DefaultLotroFormat implements LotroFormat { } @Override - public void validateDeck(Player player, LotroDeck deck) throws DeckInvalidException { + public void validateDeck(LotroDeck deck) throws DeckInvalidException { try { // Ring-bearer if (deck.getRingBearer() == null) diff --git a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/hall/HallServer.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/hall/HallServer.java index 969bb6d61..9fec5398c 100644 --- a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/hall/HallServer.java +++ b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/hall/HallServer.java @@ -7,6 +7,7 @@ import com.gempukku.lotro.chat.ChatServer; import com.gempukku.lotro.collection.CollectionsManager; import com.gempukku.lotro.db.vo.CollectionType; import com.gempukku.lotro.db.vo.League; +import com.gempukku.lotro.draft.Draft; import com.gempukku.lotro.game.*; import com.gempukku.lotro.game.formats.LotroFormatLibrary; import com.gempukku.lotro.league.LeagueSerieData; @@ -47,6 +48,7 @@ public class HallServer extends AbstractServer { private Map _lastVisitedPlayers = new HashMap(); private List _runningTournaments = new ArrayList(); + private List _running = new ArrayList(); private Map _tournamentQueues = new HashMap(); private final ChatRoomMediator _hallChat; @@ -298,7 +300,7 @@ public class HallServer extends AbstractServer { throw new HallException("You don't have a deck registered yet"); try { - format.validateDeck(player, lotroDeck); + format.validateDeck(lotroDeck); } catch (DeckInvalidException e) { throw new HallException("Your selected deck is not valid for this format: " + e.getMessage()); } diff --git a/gemp-lotr/gemp-lotr-web-server/src/main/java/com/gempukku/lotro/server/DeckResource.java b/gemp-lotr/gemp-lotr-web-server/src/main/java/com/gempukku/lotro/server/DeckResource.java index fba32a160..cf8c6aff1 100644 --- a/gemp-lotr/gemp-lotr-web-server/src/main/java/com/gempukku/lotro/server/DeckResource.java +++ b/gemp-lotr/gemp-lotr-web-server/src/main/java/com/gempukku/lotro/server/DeckResource.java @@ -222,7 +222,7 @@ public class DeckResource extends AbstractResource { for (LotroFormat format : _formatLibrary.getHallFormats().values()) { try { - format.validateDeck(resourceOwner, deck); + format.validateDeck(deck); sb.append("" + format.getName() + ": valid
"); } catch (DeckInvalidException exp) { sb.append("" + format.getName() + ": " + exp.getMessage() + "
");