- 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,
CardPrinted.FN_GET_RULES);
// Sort cards by rank.
// 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());
}
}
TreeMap<Double, CardPrinted> rankedCards = rankCards(chooseFrom);
if (this.playerColors.get(player).getColor1().equals("none")
&& this.playerColors.get(player).getColor2().equals("none")) {
// Generally the first pick of the draft, no colors selected yet.
// Sort playable cards by rank
TreeMap<Integer, CardPrinted> rankedPlayableCards = new TreeMap<Integer, CardPrinted>();
for (CardPrinted card : aiPlayables) {
Integer rkg = draftRankings.getRanking(card.getName(), card.getEdition());
if (rkg != null) {
rankedPlayableCards.put(rkg, card);
}
}
TreeMap<Double, CardPrinted> rankedPlayableCards = rankCards(aiPlayables);
pickedCard = pickCard(rankedCards, rankedPlayableCards);
@@ -157,12 +139,12 @@ public class BoosterDraftAI {
// Has already picked one color, but not the second.
// 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) {
CardColor currentColor1 = CardColor.fromNames(this.playerColors.get(player).getColor1());
CardColor color = card.getCard().getColor();
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) {
rankedPlayableCards.put(rkg, card);
}
@@ -215,13 +197,7 @@ public class BoosterDraftAI {
List<CardPrinted> colorList = hasColor.select(aiPlayables, CardPrinted.FN_GET_RULES);
// Sort playable, on-color cards by rank
TreeMap<Integer, CardPrinted> rankedPlayableCards = new TreeMap<Integer, CardPrinted>();
for (CardPrinted card : colorList) {
Integer rkg = draftRankings.getRanking(card.getName(), card.getEdition());
if (rkg != null) {
rankedPlayableCards.put(rkg, card);
}
}
TreeMap<Double, CardPrinted> rankedPlayableCards = rankCards(colorList);
pickedCard = pickCard(rankedCards, rankedPlayableCards);
}
@@ -239,6 +215,28 @@ public class BoosterDraftAI {
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.
*
@@ -246,10 +244,10 @@ public class BoosterDraftAI {
* @param rankedPlayableCards
* @return CardPrinted
*/
private CardPrinted pickCard(TreeMap<Integer, CardPrinted> rankedCards,
TreeMap<Integer, CardPrinted> rankedPlayableCards) {
private CardPrinted pickCard(TreeMap<Double, CardPrinted> rankedCards,
TreeMap<Double, CardPrinted> rankedPlayableCards) {
CardPrinted pickedCard = null;
Map.Entry<Integer, CardPrinted> best = rankedCards.firstEntry();
Map.Entry<Double, CardPrinted> best = rankedCards.firstEntry();
if (best != null) {
if (rankedPlayableCards.containsValue(best.getValue())) {
// If best card is playable, pick it.
@@ -258,7 +256,7 @@ public class BoosterDraftAI {
+ pickedCard.getCard().getManaCost() + ") " + pickedCard.getType().toString());
} else {
// 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) {
// Nothing is playable, so just take the best card.
pickedCard = best.getValue();

View File

@@ -641,7 +641,7 @@ public class LimitedDeck {
protected List<CardRankingBean> rankCards(List<CardPrinted> cards) {
List<CardRankingBean> ranked = new ArrayList<CardRankingBean>();
for (CardPrinted card : cards) {
Integer rkg = draftRankings.getRanking(card.getName(), card.getEdition());
Double rkg = draftRankings.getRanking(card.getName(), card.getEdition());
if (rkg != null) {
ranked.add(new CardRankingBean(rkg, card));
}
@@ -699,7 +699,7 @@ public class LimitedDeck {
*
*/
protected class CardRankingBean {
private Integer rank;
private Double rank;
private CardPrinted card;
/**
@@ -710,7 +710,7 @@ public class LimitedDeck {
* @param card
* the CardPrinted
*/
public CardRankingBean(Integer rank, CardPrinted card) {
public CardRankingBean(Double rank, CardPrinted card) {
this.rank = rank;
this.card = card;
}
@@ -718,7 +718,7 @@ public class LimitedDeck {
/**
* @return the rank
*/
public Integer getRank() {
public Double getRank() {
return rank;
}

View File

@@ -23,6 +23,7 @@ public class ReadDraftRankings {
private static final String COMMENT = "//";
private Map<String, Map<String, Integer>> draftRankings;
private Map<String, Integer> setSizes;
/**
* <p>
@@ -39,6 +40,7 @@ public class ReadDraftRankings {
* </p>
*/
private void setup() {
this.setSizes = new HashMap<String, Integer>();
this.draftRankings = this.readFile(ForgeProps.getFile(NewConstants.Draft.RANKINGS));
} // setup()
@@ -74,6 +76,11 @@ public class ReadDraftRankings {
map.put(edition, new HashMap<String, Integer>());
}
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) {
Log.warn("NumberFormatException: " + nfe.getMessage());
}
@@ -86,7 +93,9 @@ public class ReadDraftRankings {
throw new RuntimeException("ReadDraftRankings : readFile error, " + ex);
} finally {
try {
if (in != null)in.close();
if (in != null) {
in.close();
}
} catch (IOException ex) {
ex.printStackTrace();
}
@@ -95,11 +104,20 @@ public class ReadDraftRankings {
return map;
} // 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)) {
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;
}

View File

@@ -30,22 +30,22 @@ public class ReadDraftRankingsTest {
List<String> cardLines = FileUtil.readFile(new File(ForgeProps.getFile(NewConstants.CARDSFOLDER) + "/g",
"garruk_primal_hunter.txt"));
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"));
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",
"tamiyo_the_moon_sage.txt"));
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
cardLines = FileUtil.readFile(new File(ForgeProps.getFile(NewConstants.CARDSFOLDER) + "/m",
"mikaeus_the_lunarch.txt"));
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());
}
}