Merge pull request #7499 from spjspj/master

Adding in Jumpstart Elimination Custom Tournament option.  Creator of the table will be able to upload a Jumpstart Pack text file that uses the same format as here: https://github.com/magefree/mage/blob/master/Mage/src/main/resources/jumpstart/jumpstart.txt
This commit is contained in:
spjspj 2021-02-06 00:57:25 +11:00 committed by GitHub
commit 7d267061d9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 238 additions and 86 deletions

View file

@ -1,5 +1,13 @@
package mage.client.dialog;
import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;
import java.util.stream.Collectors;
import javax.swing.*;
import mage.cards.decks.Deck;
import mage.cards.decks.DeckFileFilter;
import mage.cards.decks.importer.DeckImporter;
@ -26,13 +34,6 @@ import mage.view.TableView;
import mage.view.TournamentTypeView;
import org.apache.log4j.Logger;
import javax.swing.*;
import java.awt.*;
import java.io.File;
import java.util.List;
import java.util.*;
import java.util.stream.Collectors;
/**
* App GUI: create new TOURNEY
*
@ -55,6 +56,7 @@ public class NewTournamentDialog extends MageDialog {
private boolean isRandom = false;
private boolean isRichMan = false;
private String cubeFromDeckFilename = "";
private String jumpstartPacksFilename = "";
private boolean automaticChange = false;
public NewTournamentDialog() {
@ -659,6 +661,12 @@ public class NewTournamentDialog extends MageDialog {
private void cbTournamentTypeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbTournamentTypeActionPerformed
prepareTourneyView((Integer) this.spnNumPlayers.getValue());
jumpstartPacksFilename = "";
if (cbTournamentType.getSelectedItem().toString().matches(".*Jumpstart.*Custom.*")) {
jumpstartPacksFilename = playerLoadJumpstartPacks();
}
}//GEN-LAST:event_cbTournamentTypeActionPerformed
private void btnOkActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnOkActionPerformed
@ -777,6 +785,26 @@ public class NewTournamentDialog extends MageDialog {
return "";
}
private JFileChooser fcJumpstartSelectDeck = null;
protected String playerLoadJumpstartPacks() {
if (fcJumpstartSelectDeck == null) {
fcJumpstartSelectDeck = new JFileChooser();
fcJumpstartSelectDeck.setAcceptAllFileFilterUsed(false);
fcJumpstartSelectDeck.addChoosableFileFilter(new DeckFileFilter("txt", "Jumpstart Packs (*.txt)"));
}
String lastFolder = MageFrame.getPreferences().get("lastDeckFolder", "");
if (!lastFolder.isEmpty()) {
fcJumpstartSelectDeck.setCurrentDirectory(new File(lastFolder));
}
int ret = fcJumpstartSelectDeck.showDialog(this, "Select Jumpstart Packs file");
if (ret == JFileChooser.APPROVE_OPTION) {
File file = fcJumpstartSelectDeck.getSelectedFile();
return (file.getPath());
}
return "";
}
private void cbDraftCubeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbDraftCubeActionPerformed
cubeFromDeckFilename = "";
if (cbDraftCube.getSelectedItem().toString().equals("Cube From Deck")) {
@ -951,7 +979,7 @@ public class NewTournamentDialog extends MageDialog {
private void loadRandomPacks(int version) {
String versionStr = prepareVersionStr(version, false);
List<String> packList;
java.util.List<String> packList;
String packNames;
String randomPrefs = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_TOURNAMENT_PACKS_RANDOM_DRAFT + versionStr, "");
if (!randomPrefs.isEmpty()) {
@ -1202,6 +1230,22 @@ public class NewTournamentDialog extends MageDialog {
tOptions.getLimitedOptions().setIsRandom(tournamentType.isRandom());
tOptions.getLimitedOptions().setIsRichMan(tournamentType.isRichMan());
tOptions.getLimitedOptions().setIsJumpstart(tournamentType.isJumpstart());
if (tournamentType.isJumpstart()) {
if (!(jumpstartPacksFilename.isEmpty())) {
String jumpstartPacksData = "";
try {
jumpstartPacksData = new String(Files.readAllBytes(Paths.get(jumpstartPacksFilename)));
if (jumpstartPacksData.length() > 300000) {
JOptionPane.showMessageDialog(MageFrame.getDesktop(), "Chosen file too big", "Jumpstart Packs data is too long. Please trim or choose another file.", JOptionPane.ERROR_MESSAGE);
jumpstartPacksData = "";
}
} catch (IOException e2) {
JOptionPane.showMessageDialog(MageFrame.getDesktop(), e2.getMessage(), "Error loading Jumpstart Packs data", JOptionPane.ERROR_MESSAGE);
}
tOptions.getLimitedOptions().setJumpstartPacks(jumpstartPacksData);
}
}
if (tournamentType.isCubeBooster()) {
tOptions.getLimitedOptions().setDraftCubeName(this.cbDraftCube.getSelectedItem().toString());
if (!(cubeFromDeckFilename.isEmpty())) {
@ -1220,7 +1264,7 @@ public class NewTournamentDialog extends MageDialog {
this.isRandom = tournamentType.isRandom();
this.isRichMan = tournamentType.isRichMan();
tOptions.getLimitedOptions().getSetCodes().clear();
List<String> selected = randomPackSelector.getSelectedPacks();
java.util.List<String> selected = randomPackSelector.getSelectedPacks();
Collections.shuffle(selected);
int maxPacks = 3 * (players.size() + 1);
if (tournamentType.isRichMan()) {

View file

@ -0,0 +1,43 @@
package mage.tournament;
import mage.game.tournament.TournamentOptions;
import mage.game.tournament.TournamentSingleElimination;
public class JumpstartCustomEliminationTournament extends TournamentSingleElimination {
protected enum TournamentStep {
START, OPEN_BOOSTERS, CONSTRUCT, COMPETE, WINNERS
}
protected TournamentStep currentStep;
public JumpstartCustomEliminationTournament(TournamentOptions options) {
super(options);
currentStep = TournamentStep.START;
}
@Override
public void nextStep() {
switch (currentStep) {
case START:
currentStep = TournamentStep.OPEN_BOOSTERS;
openBoosters();
break;
case OPEN_BOOSTERS:
currentStep = TournamentStep.CONSTRUCT;
construct();
break;
case CONSTRUCT:
currentStep = TournamentStep.COMPETE;
runTournament();
break;
case COMPETE:
currentStep = TournamentStep.WINNERS;
winners();
end();
break;
}
}
}

View file

@ -0,0 +1,19 @@
package mage.tournament;
import mage.game.tournament.TournamentType;
public class JumpstartCustomEliminationTournamentType extends TournamentType {
public JumpstartCustomEliminationTournamentType() {
this.name = "Jumpstart Elimination (Custom)";
this.maxPlayers = 16;
this.minPlayers = 2;
this.numBoosters = 0;
this.isJumpstart = true;
this.elimination = true;
this.limited = true;
}
}

View file

@ -95,7 +95,9 @@
<tournamentType name="Booster Draft Elimination" jar="mage-tournament-booster-draft.jar" className="mage.tournament.BoosterDraftEliminationTournament" typeName="mage.tournament.BoosterDraftEliminationTournamentType"/>
<tournamentType name="Booster Draft Elimination (Cube)" jar="mage-tournament-booster-draft.jar" className="mage.tournament.BoosterDraftEliminationTournament" typeName="mage.tournament.BoosterDraftEliminationCubeTournamentType"/>
<tournamentType name="Booster Draft Elimination (Random)" jar="mage-tournament-booster-draft.jar" className="mage.tournament.RandomBoosterDraftEliminationTournament" typeName="mage.tournament.RandomBoosterDraftEliminationTournamentType"/>
<tournamentType name="Booster Draft Elimination (Rich Man)" jar="mage-tournament-booster-draft.jar" className="mage.tournament.RichManDraftEliminationTournament" typeName="mage.tournament.RichManDraftEliminationTournamentType"/>
<tournamentType name="Booster Draft Elimination (Rich Man Cube)" jar="mage-tournament-booster-draft.jar" className="mage.tournament.RichManCubeDraftEliminationTournament" typeName="mage.tournament.RichManCubeDraftEliminationTournamentType"/>
<tournamentType name="Booster Draft Swiss" jar="mage-tournament-booster-draft.jar" className="mage.tournament.BoosterDraftSwissTournament" typeName="mage.tournament.BoosterDraftSwissTournamentType"/>
<tournamentType name="Booster Draft Swiss (Cube)" jar="mage-tournament-booster-draft.jar" className="mage.tournament.BoosterDraftSwissTournament" typeName="mage.tournament.BoosterDraftSwissCubeTournamentType"/>
@ -106,6 +108,7 @@
<tournamentType name="Sealed Swiss (Cube)" jar="mage-tournament-sealed.jar" className="mage.tournament.SealedSwissTournament" typeName="mage.tournament.SealedSwissCubeTournamentType"/>
<tournamentType name="Jumpstart Elimination" jar="mage-tournament-sealed.jar" className="mage.tournament.JumpstartEliminationTournament" typeName="mage.tournament.JumpstartEliminationTournamentType"/>
<tournamentType name="Jumpstart Swiss" jar="mage-tournament-sealed.jar" className="mage.tournament.JumpstartSwissTournament" typeName="mage.tournament.JumpstartSwissTournamentType"/>
<tournamentType name="Jumpstart Elimination (Custom)" jar="mage-tournament-sealed.jar" className="mage.tournament.JumpstartCustomEliminationTournament" typeName="mage.tournament.JumpstartCustomEliminationTournamentType"/>
</tournamentTypes>
<draftCubes>
<draftCube name="Adam Styborski's Pauper Cube" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.AdamStyborskisPauperCube"/>

View file

@ -100,6 +100,7 @@
<tournamentType name="Sealed Swiss (Cube)" jar="mage-tournament-sealed-${project.version}.jar" className="mage.tournament.SealedSwissTournament" typeName="mage.tournament.SealedSwissCubeTournamentType"/>
<tournamentType name="Jumpstart Elimination" jar="mage-tournament-sealed-${project.version}.jar" className="mage.tournament.JumpstartEliminationTournament" typeName="mage.tournament.JumpstartEliminationTournamentType"/>
<tournamentType name="Jumpstart Swiss" jar="mage-tournament-sealed-${project.version}.jar" className="mage.tournament.JumpstartSwissTournament" typeName="mage.tournament.JumpstartSwissTournamentType"/>
<tournamentType name="Jumpstart Elimination (Custom)" jar="mage-tournament-sealed-${project.version}.jar" className="mage.tournament.JumpstartEliminationCustomTournament" typeName="mage.tournament.JumpstartEliminationCustomTournamentType"/>
</tournamentTypes>
<draftCubes>
<draftCube name="Adam Styborski's Pauper Cube" jar="mage-tournament-booster-draft-${project.version}.jar" className="mage.tournament.cubes.AdamStyborskisPauperCube"/>

View file

@ -72,6 +72,7 @@
<tournamentType name="Sealed Swiss (Cube)" jar="mage-tournament-sealed.jar" className="mage.tournament.SealedSwissTournament" typeName="mage.tournament.SealedSwissCubeTournamentType"/>
<tournamentType name="Jumpstart Elimination" jar="mage-tournament-sealed.jar" className="mage.tournament.JumpstartEliminationTournament" typeName="mage.tournament.JumpstartEliminationTournamentType"/>
<tournamentType name="Jumpstart Swiss" jar="mage-tournament-sealed.jar" className="mage.tournament.JumpstartSwissTournament" typeName="mage.tournament.JumpstartSwissTournamentType"/>
<tournamentType name="Jumpstart Elimination (Custom)" jar="mage-tournament-sealed.jar" className="mage.tournament.JumpstartCustomEliminationTournament" typeName="mage.tournament.JumpstartCustomEliminationTournamentType"/>
</tournamentTypes>
<draftCubes>
<draftCube name="Adam Styborski's Pauper Cube" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.AdamStyborskisPauperCube"/>

View file

@ -1,5 +1,8 @@
package mage.game.jumpstart;
import com.google.common.base.Charsets;
import com.google.common.io.CharSource;
import com.google.common.io.Resources;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.security.SecureRandom;
@ -7,11 +10,6 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import com.google.common.base.Charsets;
import com.google.common.io.CharSource;
import com.google.common.io.Resources;
import mage.cards.Card;
import mage.cards.decks.Deck;
import mage.cards.decks.DeckCardInfo;
@ -49,13 +47,22 @@ public class JumpstartPoolGenerator {
* Card Pool: https://magic.wizards.com/en/articles/archive/card-image-gallery/jumpstart
* Deck Lists: https://magic.wizards.com/en/articles/archive/feature/jumpstart-decklists-2020-06-18
*/
private static final String RESOURCE_NAME = "jumpstart/jumpstart.txt";
private static final List<JumpstartPack> JUMPSTART_PACKS;
static {
List<JumpstartPack> packs = getPacks ("", true);
JUMPSTART_PACKS = Collections.unmodifiableList(packs);
}
private static List<JumpstartPack> getPacks(String jumpstartPacks, boolean useDefault) {
try {
CharSource source = Resources.asCharSource(Resources.getResource(RESOURCE_NAME), Charsets.UTF_8);
CharSource source;
if (useDefault) {
source = Resources.asCharSource(Resources.getResource(RESOURCE_NAME), Charsets.UTF_8);
} else {
source = CharSource.wrap(jumpstartPacks);
}
List<JumpstartPack> packs = new ArrayList<>();
JumpstartPack pack = new JumpstartPack();
packs.add(pack);
@ -75,12 +82,26 @@ public class JumpstartPoolGenerator {
}
}
}
JUMPSTART_PACKS = Collections.unmodifiableList(packs);
return packs;
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
private static Set<Card> doGeneratePool(List<JumpstartPack> packs) {
try {
DeckCardLists list = new DeckCardLists();
SecureRandom random = new SecureRandom();
for (int i = 0; i < 2; i++) {
int index = random.nextInt(packs.size());
list.getCards().addAll(packs.get(index).getCards());
}
return Deck.load(list, false, false).getCards();
} catch (GameException e) {
throw new RuntimeException(e);
}
}
/* Notes
*
* 1) the pools generated by this method are for how the prerelease will be played (see https://mtg.gamepedia.com/Jumpstart#Events)
@ -95,17 +116,15 @@ public class JumpstartPoolGenerator {
* https://mtg.gamepedia.com/Jumpstart#Marketing
*/
public static Set<Card> generatePool() {
try {
DeckCardLists list = new DeckCardLists();
SecureRandom random = new SecureRandom();
for (int i = 0; i < 2; i++) {
int index = random.nextInt(JUMPSTART_PACKS.size());
list.getCards().addAll(JUMPSTART_PACKS.get(index).getCards());
return doGeneratePool(JUMPSTART_PACKS);
}
return Deck.load(list, false, false).getCards();
} catch (GameException e) {
throw new RuntimeException(e);
public static Set<Card> generatePool(String userJumpstartPacks) {
if (userJumpstartPacks == null || userJumpstartPacks.length() > 300000) {
return generatePool();
}
List<JumpstartPack> packs = getPacks(userJumpstartPacks, false);
return doGeneratePool(packs);
}
public static class JumpstartPack {

View file

@ -1,11 +1,10 @@
package mage.game.tournament;
import mage.cards.decks.Deck;
import mage.game.draft.DraftCube;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import mage.cards.decks.Deck;
import mage.game.draft.DraftCube;
/**
* @author BetaSteward_at_googlemail.com
@ -20,6 +19,20 @@ public class LimitedOptions implements Serializable {
protected boolean isRandom;
protected boolean isRichMan;
protected Deck cubeFromDeck;
protected String jumpstartPacks;
// Eg of jumpstartPacks - uploaded by user
/*
# Minions
1 JMP 236 Ghoulcaller Gisa
1 JMP 226 Dutiful Attendant
1 M21 126 Village Rites
# Phyrexian
1 JMP 278 Sheoldred, Whispering One
1 JMP 227 Entomber Exarch
1 JMP 265 Phyrexian Gargantua
*/
protected boolean isJumpstart;
public List<String> getSetCodes() {
@ -50,6 +63,14 @@ public class LimitedOptions implements Serializable {
return cubeFromDeck;
}
public void setJumpstartPacks(String jumpstartPacks) {
this.jumpstartPacks = jumpstartPacks;
}
public String getJumpstartPacks() {
return jumpstartPacks;
}
public DraftCube getDraftCube() {
return draftCube;
}

View file

@ -1,4 +1,3 @@
package mage.game.tournament;
import java.util.ArrayList;
@ -12,9 +11,6 @@ import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CopyOnWriteArrayList;
import org.apache.log4j.Logger;
import mage.cards.ExpansionSet;
import mage.cards.decks.Deck;
import mage.constants.TournamentPlayerState;
@ -37,6 +33,7 @@ import mage.game.result.ResultProtos.TourneyRoundProto;
import mage.players.Player;
import mage.players.PlayerType;
import mage.util.RandomUtil;
import org.apache.log4j.Logger;
/**
*
@ -411,7 +408,11 @@ public abstract class TournamentImpl implements Tournament {
player.getDeck().getSideboard().addAll(cube.createBooster());
}
} else if (options.getLimitedOptions().getIsJumpstart()) {
if (options.getLimitedOptions().jumpstartPacks == null) {
player.getDeck().getCards().addAll(JumpstartPoolGenerator.generatePool());
} else {
player.getDeck().getCards().addAll(JumpstartPoolGenerator.generatePool(options.getLimitedOptions().jumpstartPacks));
}
} else {
for (ExpansionSet set : sets) {
player.getDeck().getSideboard().addAll(set.createBooster());