mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-17 19:28:01 +00:00
- improve DraftRankings to handle sets with different number of cards
This commit is contained in:
@@ -77,32 +77,14 @@ public class BoosterDraftAI {
|
|||||||
List<CardPrinted> aiPlayables = CardRules.Predicates.IS_KEPT_IN_AI_DECKS.select(chooseFrom,
|
List<CardPrinted> aiPlayables = CardRules.Predicates.IS_KEPT_IN_AI_DECKS.select(chooseFrom,
|
||||||
CardPrinted.FN_GET_RULES);
|
CardPrinted.FN_GET_RULES);
|
||||||
|
|
||||||
// Sort cards by rank.
|
TreeMap<Double, CardPrinted> rankedCards = rankCards(chooseFrom);
|
||||||
// Note that if pack has cards from different editions, they could have
|
|
||||||
// the same Integer rank.
|
|
||||||
// In that (hopefully rare) case, only one will end up in the Map.
|
|
||||||
TreeMap<Integer, CardPrinted> rankedCards = new TreeMap<Integer, CardPrinted>();
|
|
||||||
for (CardPrinted card : chooseFrom) {
|
|
||||||
Integer rkg = draftRankings.getRanking(card.getName(), card.getEdition());
|
|
||||||
if (rkg != null) {
|
|
||||||
rankedCards.put(rkg, card);
|
|
||||||
} else {
|
|
||||||
System.out.println("Draft Rankings - Card Not Found: " + card.getName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.playerColors.get(player).getColor1().equals("none")
|
if (this.playerColors.get(player).getColor1().equals("none")
|
||||||
&& this.playerColors.get(player).getColor2().equals("none")) {
|
&& this.playerColors.get(player).getColor2().equals("none")) {
|
||||||
// Generally the first pick of the draft, no colors selected yet.
|
// Generally the first pick of the draft, no colors selected yet.
|
||||||
|
|
||||||
// Sort playable cards by rank
|
// Sort playable cards by rank
|
||||||
TreeMap<Integer, CardPrinted> rankedPlayableCards = new TreeMap<Integer, CardPrinted>();
|
TreeMap<Double, CardPrinted> rankedPlayableCards = rankCards(aiPlayables);
|
||||||
for (CardPrinted card : aiPlayables) {
|
|
||||||
Integer rkg = draftRankings.getRanking(card.getName(), card.getEdition());
|
|
||||||
if (rkg != null) {
|
|
||||||
rankedPlayableCards.put(rkg, card);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pickedCard = pickCard(rankedCards, rankedPlayableCards);
|
pickedCard = pickCard(rankedCards, rankedPlayableCards);
|
||||||
|
|
||||||
@@ -157,12 +139,12 @@ public class BoosterDraftAI {
|
|||||||
// Has already picked one color, but not the second.
|
// Has already picked one color, but not the second.
|
||||||
|
|
||||||
// Sort playable, on-color, or mono-colored, or colorless cards
|
// Sort playable, on-color, or mono-colored, or colorless cards
|
||||||
TreeMap<Integer, CardPrinted> rankedPlayableCards = new TreeMap<Integer, CardPrinted>();
|
TreeMap<Double, CardPrinted> rankedPlayableCards = new TreeMap<Double, CardPrinted>();
|
||||||
for (CardPrinted card : aiPlayables) {
|
for (CardPrinted card : aiPlayables) {
|
||||||
CardColor currentColor1 = CardColor.fromNames(this.playerColors.get(player).getColor1());
|
CardColor currentColor1 = CardColor.fromNames(this.playerColors.get(player).getColor1());
|
||||||
CardColor color = card.getCard().getColor();
|
CardColor color = card.getCard().getColor();
|
||||||
if (color.isColorless() || color.sharesColorWith(currentColor1) || color.isMonoColor()) {
|
if (color.isColorless() || color.sharesColorWith(currentColor1) || color.isMonoColor()) {
|
||||||
Integer rkg = draftRankings.getRanking(card.getName(), card.getEdition());
|
Double rkg = draftRankings.getRanking(card.getName(), card.getEdition());
|
||||||
if (rkg != null) {
|
if (rkg != null) {
|
||||||
rankedPlayableCards.put(rkg, card);
|
rankedPlayableCards.put(rkg, card);
|
||||||
}
|
}
|
||||||
@@ -215,13 +197,7 @@ public class BoosterDraftAI {
|
|||||||
List<CardPrinted> colorList = hasColor.select(aiPlayables, CardPrinted.FN_GET_RULES);
|
List<CardPrinted> colorList = hasColor.select(aiPlayables, CardPrinted.FN_GET_RULES);
|
||||||
|
|
||||||
// Sort playable, on-color cards by rank
|
// Sort playable, on-color cards by rank
|
||||||
TreeMap<Integer, CardPrinted> rankedPlayableCards = new TreeMap<Integer, CardPrinted>();
|
TreeMap<Double, CardPrinted> rankedPlayableCards = rankCards(colorList);
|
||||||
for (CardPrinted card : colorList) {
|
|
||||||
Integer rkg = draftRankings.getRanking(card.getName(), card.getEdition());
|
|
||||||
if (rkg != null) {
|
|
||||||
rankedPlayableCards.put(rkg, card);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pickedCard = pickCard(rankedCards, rankedPlayableCards);
|
pickedCard = pickCard(rankedCards, rankedPlayableCards);
|
||||||
}
|
}
|
||||||
@@ -239,6 +215,28 @@ public class BoosterDraftAI {
|
|||||||
return pickedCard;
|
return pickedCard;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sort cards by rank. Note that if pack has cards from different editions,
|
||||||
|
* they could have the same rank. In that (hopefully rare) case, only one
|
||||||
|
* will end up in the Map.
|
||||||
|
*
|
||||||
|
* @param chooseFrom
|
||||||
|
* List of cards
|
||||||
|
* @return map of rankings
|
||||||
|
*/
|
||||||
|
private TreeMap<Double, CardPrinted> rankCards(final List<CardPrinted> chooseFrom) {
|
||||||
|
TreeMap<Double, CardPrinted> rankedCards = new TreeMap<Double, CardPrinted>();
|
||||||
|
for (CardPrinted card : chooseFrom) {
|
||||||
|
Double rkg = draftRankings.getRanking(card.getName(), card.getEdition());
|
||||||
|
if (rkg != null) {
|
||||||
|
rankedCards.put(rkg, card);
|
||||||
|
} else {
|
||||||
|
System.out.println("Draft Rankings - Card Not Found: " + card.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rankedCards;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pick a card.
|
* Pick a card.
|
||||||
*
|
*
|
||||||
@@ -246,10 +244,10 @@ public class BoosterDraftAI {
|
|||||||
* @param rankedPlayableCards
|
* @param rankedPlayableCards
|
||||||
* @return CardPrinted
|
* @return CardPrinted
|
||||||
*/
|
*/
|
||||||
private CardPrinted pickCard(TreeMap<Integer, CardPrinted> rankedCards,
|
private CardPrinted pickCard(TreeMap<Double, CardPrinted> rankedCards,
|
||||||
TreeMap<Integer, CardPrinted> rankedPlayableCards) {
|
TreeMap<Double, CardPrinted> rankedPlayableCards) {
|
||||||
CardPrinted pickedCard = null;
|
CardPrinted pickedCard = null;
|
||||||
Map.Entry<Integer, CardPrinted> best = rankedCards.firstEntry();
|
Map.Entry<Double, CardPrinted> best = rankedCards.firstEntry();
|
||||||
if (best != null) {
|
if (best != null) {
|
||||||
if (rankedPlayableCards.containsValue(best.getValue())) {
|
if (rankedPlayableCards.containsValue(best.getValue())) {
|
||||||
// If best card is playable, pick it.
|
// If best card is playable, pick it.
|
||||||
@@ -258,7 +256,7 @@ public class BoosterDraftAI {
|
|||||||
+ pickedCard.getCard().getManaCost() + ") " + pickedCard.getType().toString());
|
+ pickedCard.getCard().getManaCost() + ") " + pickedCard.getType().toString());
|
||||||
} else {
|
} else {
|
||||||
// If not, find the best card that is playable.
|
// If not, find the best card that is playable.
|
||||||
Map.Entry<Integer, CardPrinted> bestPlayable = rankedPlayableCards.firstEntry();
|
Map.Entry<Double, CardPrinted> bestPlayable = rankedPlayableCards.firstEntry();
|
||||||
if (bestPlayable == null) {
|
if (bestPlayable == null) {
|
||||||
// Nothing is playable, so just take the best card.
|
// Nothing is playable, so just take the best card.
|
||||||
pickedCard = best.getValue();
|
pickedCard = best.getValue();
|
||||||
|
|||||||
@@ -641,7 +641,7 @@ public class LimitedDeck {
|
|||||||
protected List<CardRankingBean> rankCards(List<CardPrinted> cards) {
|
protected List<CardRankingBean> rankCards(List<CardPrinted> cards) {
|
||||||
List<CardRankingBean> ranked = new ArrayList<CardRankingBean>();
|
List<CardRankingBean> ranked = new ArrayList<CardRankingBean>();
|
||||||
for (CardPrinted card : cards) {
|
for (CardPrinted card : cards) {
|
||||||
Integer rkg = draftRankings.getRanking(card.getName(), card.getEdition());
|
Double rkg = draftRankings.getRanking(card.getName(), card.getEdition());
|
||||||
if (rkg != null) {
|
if (rkg != null) {
|
||||||
ranked.add(new CardRankingBean(rkg, card));
|
ranked.add(new CardRankingBean(rkg, card));
|
||||||
}
|
}
|
||||||
@@ -699,7 +699,7 @@ public class LimitedDeck {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
protected class CardRankingBean {
|
protected class CardRankingBean {
|
||||||
private Integer rank;
|
private Double rank;
|
||||||
private CardPrinted card;
|
private CardPrinted card;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -710,7 +710,7 @@ public class LimitedDeck {
|
|||||||
* @param card
|
* @param card
|
||||||
* the CardPrinted
|
* the CardPrinted
|
||||||
*/
|
*/
|
||||||
public CardRankingBean(Integer rank, CardPrinted card) {
|
public CardRankingBean(Double rank, CardPrinted card) {
|
||||||
this.rank = rank;
|
this.rank = rank;
|
||||||
this.card = card;
|
this.card = card;
|
||||||
}
|
}
|
||||||
@@ -718,7 +718,7 @@ public class LimitedDeck {
|
|||||||
/**
|
/**
|
||||||
* @return the rank
|
* @return the rank
|
||||||
*/
|
*/
|
||||||
public Integer getRank() {
|
public Double getRank() {
|
||||||
return rank;
|
return rank;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ public class ReadDraftRankings {
|
|||||||
private static final String COMMENT = "//";
|
private static final String COMMENT = "//";
|
||||||
|
|
||||||
private Map<String, Map<String, Integer>> draftRankings;
|
private Map<String, Map<String, Integer>> draftRankings;
|
||||||
|
private Map<String, Integer> setSizes;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
@@ -39,6 +40,7 @@ public class ReadDraftRankings {
|
|||||||
* </p>
|
* </p>
|
||||||
*/
|
*/
|
||||||
private void setup() {
|
private void setup() {
|
||||||
|
this.setSizes = new HashMap<String, Integer>();
|
||||||
this.draftRankings = this.readFile(ForgeProps.getFile(NewConstants.Draft.RANKINGS));
|
this.draftRankings = this.readFile(ForgeProps.getFile(NewConstants.Draft.RANKINGS));
|
||||||
} // setup()
|
} // setup()
|
||||||
|
|
||||||
@@ -74,6 +76,11 @@ public class ReadDraftRankings {
|
|||||||
map.put(edition, new HashMap<String, Integer>());
|
map.put(edition, new HashMap<String, Integer>());
|
||||||
}
|
}
|
||||||
map.get(edition).put(name, rank);
|
map.get(edition).put(name, rank);
|
||||||
|
if (setSizes.containsKey(edition)) {
|
||||||
|
setSizes.put(edition, Math.max(setSizes.get(edition), rank));
|
||||||
|
} else {
|
||||||
|
setSizes.put(edition, rank);
|
||||||
|
}
|
||||||
} catch (NumberFormatException nfe) {
|
} catch (NumberFormatException nfe) {
|
||||||
Log.warn("NumberFormatException: " + nfe.getMessage());
|
Log.warn("NumberFormatException: " + nfe.getMessage());
|
||||||
}
|
}
|
||||||
@@ -86,7 +93,9 @@ public class ReadDraftRankings {
|
|||||||
throw new RuntimeException("ReadDraftRankings : readFile error, " + ex);
|
throw new RuntimeException("ReadDraftRankings : readFile error, " + ex);
|
||||||
} finally {
|
} finally {
|
||||||
try {
|
try {
|
||||||
if (in != null)in.close();
|
if (in != null) {
|
||||||
|
in.close();
|
||||||
|
}
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
ex.printStackTrace();
|
ex.printStackTrace();
|
||||||
}
|
}
|
||||||
@@ -95,11 +104,20 @@ public class ReadDraftRankings {
|
|||||||
return map;
|
return map;
|
||||||
} // readFile()
|
} // readFile()
|
||||||
|
|
||||||
public Integer getRanking(String cardName, String edition) {
|
/**
|
||||||
Integer rank = null;
|
* Get the relative ranking for the given card name in the given edition.
|
||||||
|
*
|
||||||
|
* @param cardName
|
||||||
|
* the card name
|
||||||
|
* @param edition
|
||||||
|
* the card's edition
|
||||||
|
* @return ranking
|
||||||
|
*/
|
||||||
|
public Double getRanking(String cardName, String edition) {
|
||||||
|
Double rank = null;
|
||||||
if (draftRankings.containsKey(edition)) {
|
if (draftRankings.containsKey(edition)) {
|
||||||
String safeName = cardName.replaceAll("-", " ").replaceAll("[^A-Za-z ]", "");
|
String safeName = cardName.replaceAll("-", " ").replaceAll("[^A-Za-z ]", "");
|
||||||
rank = draftRankings.get(edition).get(safeName);
|
rank = (double) draftRankings.get(edition).get(safeName) / (double) setSizes.get(edition);
|
||||||
}
|
}
|
||||||
return rank;
|
return rank;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,22 +30,22 @@ public class ReadDraftRankingsTest {
|
|||||||
List<String> cardLines = FileUtil.readFile(new File(ForgeProps.getFile(NewConstants.CARDSFOLDER) + "/g",
|
List<String> cardLines = FileUtil.readFile(new File(ForgeProps.getFile(NewConstants.CARDSFOLDER) + "/g",
|
||||||
"garruk_primal_hunter.txt"));
|
"garruk_primal_hunter.txt"));
|
||||||
Card c = CardReader.readCard(cardLines);
|
Card c = CardReader.readCard(cardLines);
|
||||||
Assert.assertEquals(1, rdr.getRanking(c.getName(), "M13").intValue());
|
Assert.assertEquals(1.0 / 234.0, rdr.getRanking(c.getName(), "M13").doubleValue());
|
||||||
|
|
||||||
cardLines = FileUtil.readFile(new File(ForgeProps.getFile(NewConstants.CARDSFOLDER) + "/c", "clone.txt"));
|
cardLines = FileUtil.readFile(new File(ForgeProps.getFile(NewConstants.CARDSFOLDER) + "/c", "clone.txt"));
|
||||||
c = CardReader.readCard(cardLines);
|
c = CardReader.readCard(cardLines);
|
||||||
Assert.assertEquals(38, rdr.getRanking(c.getName(), "M13").intValue());
|
Assert.assertEquals(38.0 / 234.0, rdr.getRanking(c.getName(), "M13").doubleValue());
|
||||||
|
|
||||||
cardLines = FileUtil.readFile(new File(ForgeProps.getFile(NewConstants.CARDSFOLDER) + "/t",
|
cardLines = FileUtil.readFile(new File(ForgeProps.getFile(NewConstants.CARDSFOLDER) + "/t",
|
||||||
"tamiyo_the_moon_sage.txt"));
|
"tamiyo_the_moon_sage.txt"));
|
||||||
c = CardReader.readCard(cardLines);
|
c = CardReader.readCard(cardLines);
|
||||||
Assert.assertEquals(1, rdr.getRanking(c.getName(), "AVR").intValue());
|
Assert.assertEquals(1.0 / 234.0, rdr.getRanking(c.getName(), "AVR").doubleValue());
|
||||||
|
|
||||||
// Mikaeus, the Lunarch has a comma in its name in the rankings file
|
// Mikaeus, the Lunarch has a comma in its name in the rankings file
|
||||||
cardLines = FileUtil.readFile(new File(ForgeProps.getFile(NewConstants.CARDSFOLDER) + "/m",
|
cardLines = FileUtil.readFile(new File(ForgeProps.getFile(NewConstants.CARDSFOLDER) + "/m",
|
||||||
"mikaeus_the_lunarch.txt"));
|
"mikaeus_the_lunarch.txt"));
|
||||||
c = CardReader.readCard(cardLines);
|
c = CardReader.readCard(cardLines);
|
||||||
Assert.assertEquals(4, rdr.getRanking(c.getName(), "ISD").intValue());
|
Assert.assertEquals(4.0 / 255.0, rdr.getRanking(c.getName(), "ISD").doubleValue());
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user