- improve DraftRankings to handle sets with different number of cards

This commit is contained in:
mcrawford620
2012-08-27 17:04:02 +00:00
parent 8fe22e6bdb
commit feffeea5b4
4 changed files with 61 additions and 45 deletions

View File

@@ -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();

View File

@@ -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;
} }

View File

@@ -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;
} }

View File

@@ -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());
} }
} }