Added cubes for Sealed and Daft Tournaments. Added a simple Swiss like tournament format.

This commit is contained in:
LevelX2 2014-01-10 19:58:55 +01:00
parent e3d543fa76
commit e490d6af61
44 changed files with 3119 additions and 246 deletions

View file

@ -43,7 +43,7 @@ public class BoosterDraft extends DraftImpl<BoosterDraft> {
@Override
public void start() {
while (boosterNum < sets.size()) {
while (boosterNum < numberBoosters) {
openBooster();
while (!isAbort() && pickCards()) {
if (boosterNum % 2 == 1) {

View file

@ -49,6 +49,8 @@ public interface Draft extends MageItem, Serializable {
Collection<DraftPlayer> getPlayers();
boolean replacePlayer(Player oldPlayer, Player newPlayer);
DraftPlayer getPlayer(UUID playerId);
int getNumberBoosters();
DraftCube getDraftCube();
List<ExpansionSet> getSets();
int getBoosterNum();
int getCardNum();

View file

@ -0,0 +1,141 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.game.draft;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import mage.cards.Card;
import mage.cards.repository.CardCriteria;
import mage.cards.repository.CardInfo;
import mage.cards.repository.CardRepository;
import org.apache.log4j.Logger;
/**
*
* @author LevelX2
*/
public abstract class DraftCube {
public class CardIdentity {
private String name;
private String extension;
public CardIdentity(String name, String extension) {
this.name = name;
this.extension = extension;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getExtension() {
return extension;
}
public void setExtension(String extension) {
this.extension = extension;
}
}
private static final Logger logger = Logger.getLogger(DraftCube.class);
private static Random rnd = new Random();
private String name;
private int boosterSize = 15;
protected List<CardIdentity> cubeCards = new ArrayList<CardIdentity>();
protected List<CardIdentity> leftCubeCards = new ArrayList<CardIdentity>();
public DraftCube(String name) {
this.name = name;
}
public String getName() {
return name;
}
public List<CardIdentity> getCubeCards() {
return cubeCards;
}
public List<Card> createBooster() {
List<Card> booster = new ArrayList<Card>();
if (leftCubeCards.isEmpty()) {
leftCubeCards.addAll(cubeCards);
}
for (int i = 0; i < boosterSize; i++) {
boolean done = false;
int notValid = 0;
while (!done) {
int index = rnd.nextInt(leftCubeCards.size());
CardIdentity cardId = leftCubeCards.get(index);
leftCubeCards.remove(index);
if (!cardId.getName().isEmpty()) {
CardInfo cardInfo = null;
if (!cardId.getExtension().isEmpty()) {
CardCriteria criteria = new CardCriteria().name(cardId.getName()).setCodes(cardId.extension);
List<CardInfo> cardList = CardRepository.instance.findCards(criteria);
if (cardList != null && cardList.size() > 0) {
cardInfo = cardList.get(0);
}
} else {
cardInfo = CardRepository.instance.findCard(cardId.getName());
}
if (cardInfo != null) {
booster.add(cardInfo.getCard());
done = true;
} else {
logger.error(new StringBuilder(this.getName()).append(" - Card not found: ").append(cardId.getName()).append(":").append(cardId.extension));
notValid++;
}
} else {
logger.error(new StringBuilder(this.getName()).append(" - Empty card name: ").append(cardId.getName()).append(":").append(cardId.extension));
notValid++;
}
if (leftCubeCards.isEmpty()) {
leftCubeCards.addAll(cubeCards);
}
if (notValid > cubeCards.size()) {
logger.error(new StringBuilder(this.getName()).append(" - Booster could not be created, no valid cards found "));
done = true;
}
}
}
return booster;
}
}

View file

@ -54,6 +54,8 @@ public abstract class DraftImpl<T extends DraftImpl<T>> implements Draft {
protected final UUID id;
protected Map<UUID, DraftPlayer> players = new HashMap<UUID, DraftPlayer>();
protected PlayerList table = new PlayerList();
protected int numberBoosters;
protected DraftCube draftCube;
protected List<ExpansionSet> sets;
protected List<String> setCodes;
protected int boosterNum = 0;
@ -69,8 +71,10 @@ public abstract class DraftImpl<T extends DraftImpl<T>> implements Draft {
public DraftImpl(DraftOptions options, List<ExpansionSet> sets) {
id = UUID.randomUUID();
this.setCodes = options.getSetCodes();
this.draftCube = options.getDraftCube();
this.timing = options.getTiming();
this.sets = sets;
this.numberBoosters = options.getNumberBoosters();
}
@Override
@ -134,6 +138,22 @@ public abstract class DraftImpl<T extends DraftImpl<T>> implements Draft {
return players.get(playerId);
}
@Override
public DraftCube getDraftCube() {
return draftCube;
}
/**
* Number of boosters that each player gets in this draft
*
* @return
*/
@Override
public int getNumberBoosters() {
return numberBoosters;
}
@Override
public List<ExpansionSet> getSets() {
return sets;
@ -207,9 +227,13 @@ public abstract class DraftImpl<T extends DraftImpl<T>> implements Draft {
protected void openBooster() {
if (boosterNum < sets.size()) {
if (boosterNum < numberBoosters) {
for (DraftPlayer player: players.values()) {
player.setBooster(sets.get(boosterNum).createBooster());
if (draftCube != null) {
player.setBooster(draftCube.createBooster());
} else {
player.setBooster(sets.get(boosterNum).createBooster());
}
}
}
boosterNum++;

View file

@ -39,7 +39,7 @@ public class DraftOptions extends LimitedOptions implements Serializable {
protected String draftType;
protected TimingOption timing;
public enum TimingOption {
REGULAR (1),
BEGINNER (2),

View file

@ -31,6 +31,7 @@ package mage.game.tournament;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import mage.game.draft.DraftCube;
/**
*
@ -40,6 +41,9 @@ public class LimitedOptions implements Serializable {
protected List<String> sets = new ArrayList<String>();
protected int constructionTime;
protected String draftCubeName;
protected DraftCube draftCube;
protected int numberBoosters;
public List<String> getSetCodes() {
return sets;
@ -52,5 +56,29 @@ public class LimitedOptions implements Serializable {
public void setConstructionTime(int constructionTime) {
this.constructionTime = constructionTime;
}
public String getDraftCubeName() {
return draftCubeName;
}
public void setDraftCubeName(String draftCubeName) {
this.draftCubeName = draftCubeName;
}
public DraftCube getDraftCube() {
return draftCube;
}
public void setDraftCube(DraftCube draftCube) {
this.draftCube = draftCube;
}
public int getNumberBoosters() {
return numberBoosters;
}
public void setNumberBoosters(int numberBoosters) {
this.numberBoosters = numberBoosters;
}
}

View file

@ -40,6 +40,7 @@ public class Round {
private int roundNum;
private List<TournamentPairing> pairs = new ArrayList<TournamentPairing>();
private List<TournamentPlayer> playerByes = new ArrayList<TournamentPlayer>();
public Round(int roundNum) {
this.roundNum = roundNum;
@ -74,4 +75,9 @@ public class Round {
}
return true;
}
public List<TournamentPlayer> getPlayerByes() {
return playerByes;
}
}

View file

@ -53,12 +53,12 @@ public interface Tournament {
Collection<Round> getRounds();
List<ExpansionSet> getSets();
void setSetsFormatedShort(String setInfo);
void setBoosterInfo(String setInfo);
/**
* Gives back a String that shows the included sets (e.g. "3xRTR" or "1xDGM 1xGTC 1xRTR")
* Gives back a String that shows the included sets (e.g. "3xRTR" or "1xDGM 1xGTC 1xRTR") or cube name
* @return String
*/
String getSetsFormatedShort();
String getBoosterInfo();
void submitDeck(UUID playerId, Deck deck);
void updateDeck(UUID playerId, Deck deck);
void autoSubmit(UUID playerId, Deck deck);
@ -80,4 +80,6 @@ public interface Tournament {
// tournament type
TournamentType getTournamentType();
void setTournamentType(TournamentType tournamentType);
int getNumberRounds();
}

View file

@ -33,6 +33,8 @@ import java.util.concurrent.CopyOnWriteArrayList;
import mage.cards.Card;
import mage.cards.ExpansionSet;
import mage.cards.decks.Deck;
import mage.constants.TournamentPlayerState;
import mage.game.draft.DraftCube;
import mage.game.events.*;
import mage.game.events.TableEvent.EventType;
import mage.game.match.Match;
@ -104,6 +106,11 @@ public abstract class TournamentImpl implements Tournament {
return players.values();
}
@Override
public int getNumberRounds() {
return options.getNumberRounds();
}
@Override
public Collection<Round> getRounds() {
return rounds;
@ -115,12 +122,12 @@ public abstract class TournamentImpl implements Tournament {
}
@Override
public void setSetsFormatedShort(String setsInfoShort) {
public void setBoosterInfo(String setsInfoShort) {
this.setsInfoShort = setsInfoShort;
}
@Override
public String getSetsFormatedShort() {
public String getBoosterInfo() {
return setsInfoShort;
}
@ -169,6 +176,13 @@ public abstract class TournamentImpl implements Tournament {
roundPlayers.remove(i);
round.addPairing(new TournamentPairing(player1, player2));
}
if (roundPlayers.size() > 0) {
// player free round - add to bye players of this round
TournamentPlayer player1 = roundPlayers.get(0);
round.getPlayerByes().add(player1);
player1.setState(TournamentPlayerState.WAITING);
player1.setStateInfo("Round Bye");
}
return round;
}
@ -203,6 +217,7 @@ public abstract class TournamentImpl implements Tournament {
for (TournamentPlayer player: players.values()) {
player.setResults("");
player.setPoints(0);
player.setStateInfo("");
}
for (Round round: rounds) {
for (TournamentPairing pair: round.getPairs()) {
@ -232,6 +247,14 @@ public abstract class TournamentImpl implements Tournament {
players.get(player2Id).setPoints(points + 1);
}
}
for (TournamentPlayer tournamentPlayer : round.getPlayerByes()) {
UUID player1Id = tournamentPlayer.getPlayer().getId();
StringBuilder sb1 = new StringBuilder(players.get(player1Id).getResults());
sb1.append("(Round Bye) ");
players.get(player1Id).setResults(sb1.toString());
int points = players.get(player1Id).getPoints();
players.get(player1Id).setPoints(points + 3);
}
}
}
@ -296,10 +319,20 @@ public abstract class TournamentImpl implements Tournament {
protected void openBoosters() {
for (TournamentPlayer player: this.players.values()) {
player.setDeck(new Deck());
for (ExpansionSet set: sets) {
List<Card> booster = set.createBooster();
for (Card card: booster) {
player.getDeck().getSideboard().add(card);
if (options.getLimitedOptions().getDraftCube() != null) {
DraftCube cube = options.getLimitedOptions().getDraftCube();
for (int i = 0; i < options.getLimitedOptions().getNumberBoosters(); i++) {
List<Card> booster = cube.createBooster();
for (Card card: booster) {
player.getDeck().getSideboard().add(card);
}
}
} else {
for (ExpansionSet set: sets) {
List<Card> booster = set.createBooster();
for (Card card: booster) {
player.getDeck().getSideboard().add(card);
}
}
}
}
@ -343,4 +376,14 @@ public abstract class TournamentImpl implements Tournament {
this.tournamentType = tournamentType;
}
protected void winners() {
// TODO: Generate StateInfo for Swiss pairing (1st, 2nd, ...)
for(TournamentPlayer winner: this.getActivePlayers()) {
winner.setState(TournamentPlayerState.FINISHED);
if (options.getNumberRounds() == 0) { // if no swiss, last active is the winner
winner.setStateInfo("Winner");
}
}
}
}

View file

@ -45,6 +45,7 @@ public class TournamentOptions implements Serializable {
protected MatchOptions matchOptions = new MatchOptions("", "Two Player Duel");
protected LimitedOptions limitedOptions;
protected boolean watchingAllowed = true;
protected int numberRounds;
public TournamentOptions(String name) {
this.name = name;
@ -86,4 +87,12 @@ public class TournamentOptions implements Serializable {
this.watchingAllowed = watchingAllowed;
}
public int getNumberRounds() {
return numberRounds;
}
public void setNumberRounds(int numberRounds) {
this.numberRounds = numberRounds;
}
}

View file

@ -30,7 +30,6 @@ package mage.game.tournament;
import java.util.Map;
import java.util.UUID;
import mage.constants.TournamentPlayerState;
/**
*
@ -66,11 +65,6 @@ public abstract class TournamentSingleElimination extends TournamentImpl {
}
}
protected void winners() {
for(TournamentPlayer winner: this.getActivePlayers()) {
winner.setState(TournamentPlayerState.FINISHED);
winner.setStateInfo("Winner");
}
}
}

View file

@ -27,6 +27,13 @@
*/
package mage.game.tournament;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import mage.constants.TournamentPlayerState;
/**
*
* @author BetaSteward_at_googlemail.com
@ -39,7 +46,86 @@ public abstract class TournamentSwiss extends TournamentImpl {
@Override
protected void runTournament() {
//TODO: implement this
for (Map.Entry<UUID, TournamentPlayer> entry: players.entrySet()) {
if (entry.getValue().getPlayer().autoLoseGame()) {
entry.getValue().setEliminated();
entry.getValue().setResults("Auto Eliminated");
}
}
while (this.getActivePlayers().size() > 1 && this.getNumberRounds() > this.getRounds().size()) {
// Swiss pairing
Round round = createRoundSwiss();
playRound(round);
}
nextStep();
}
protected Round createRoundSwiss() {
Round round = new Round(rounds.size() + 1);
rounds.add(round);
List<TournamentPlayer> roundPlayers = getActivePlayers();
// sort players by tournament points
Collections.sort(roundPlayers, new Comparator<TournamentPlayer>() {
@Override public int compare(TournamentPlayer p1, TournamentPlayer p2) {
return p2.getPoints() - p1.getPoints();
}
});
// create pairings
while (roundPlayers.size() > 0) {
TournamentPlayer player1 = roundPlayers.get(0);
roundPlayers.remove(0);
TournamentPlayer playerForPossibleSecondPairing = null;
for (TournamentPlayer player2: roundPlayers) {
if (alreadyPaired(player1, player2)) {
// if laready paired but equal ponts -> remember if second pairing is needed
if (playerForPossibleSecondPairing == null) {
playerForPossibleSecondPairing = player2;
}
} else {
if (player2.getPoints() < player1.getPoints() && playerForPossibleSecondPairing != null) {
// pair again with a player
round.addPairing(new TournamentPairing(player1, playerForPossibleSecondPairing));
roundPlayers.remove(playerForPossibleSecondPairing);
player1 = null;
break;
} else {
// pair agains the next not paired before
round.addPairing(new TournamentPairing(player1, player2));
roundPlayers.remove(player2);
player1 = null;
break;
}
}
}
if (player1 != null) {
// no pairing done yet
if (playerForPossibleSecondPairing != null) {
// pair again with a player
round.addPairing(new TournamentPairing(player1, playerForPossibleSecondPairing));
roundPlayers.remove(playerForPossibleSecondPairing);
} else {
// player free round - add to bye players of this round
round.getPlayerByes().add(player1);
player1.setState(TournamentPlayerState.WAITING);
player1.setStateInfo("Round Bye");
}
}
}
return round;
}
protected boolean alreadyPaired(TournamentPlayer player1, TournamentPlayer player2) {
for (Round round : rounds) {
for (TournamentPairing pairing: round.getPairs()) {
if (pairing.getPlayer1().equals(player1) || pairing.getPlayer2().equals(player1)) {
if (pairing.getPlayer1().equals(player2) || pairing.getPlayer2().equals(player2)) {
return true;
}
}
}
}
return false;
}
}

View file

@ -40,8 +40,10 @@ public class TournamentType <T extends TournamentType<T>> implements Serializabl
protected int minPlayers;
protected int maxPlayers;
protected int numBoosters;
protected boolean draft;
protected boolean limited;
protected boolean cubeBooster; // boosters are generated from a defined cube
protected boolean draft; // or sealed
protected boolean limited; // or construced
protected boolean elimination; // or Swiss
protected TournamentType() {}
@ -73,4 +75,13 @@ public class TournamentType <T extends TournamentType<T>> implements Serializabl
public boolean isLimited() {
return limited;
}
public boolean isElimination() {
return elimination;
}
public boolean isCubeBooster() {
return cubeBooster;
}
}