Refactored card cache;

This commit is contained in:
magenoxx 2012-06-26 16:17:25 +04:00
parent 96daa4e0a9
commit 5fa99262bf
4 changed files with 132 additions and 123 deletions

View file

@ -10,7 +10,7 @@ import java.io.*;
public class CacheDataHelper {
private static final Logger log = Logger.getLogger(CacheDataHelper.class);
/**
* Save object on disk.
*
@ -93,4 +93,24 @@ public class CacheDataHelper {
}
}
/**
* Validates cache for being consistent.
*
* @param cache
* @return
*/
public static boolean validateCache(Cache cache, int cacheVersion, int cardCount, String countKey) {
if (cache == null || cache.getVersion() != cacheVersion) {
return false;
}
Object object = cache.getCacheObjects().get(countKey);
if (object == null || !(object instanceof Integer)) {
return false;
}
Integer count = (Integer) object;
if (!count.equals(cardCount)) {
return false;
}
return true;
}
}

View file

@ -0,0 +1,94 @@
package mage.cache;
import mage.Constants;
import mage.cards.Card;
import org.apache.log4j.Logger;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
/**
* @author noxx
*/
public class CacheService {
private static final Logger log = Logger.getLogger(CacheService.class);
private static final String NAMES_CACHE_OBJECT_NAME = "card_names";
private static final String NAMES_KEY = "card_names_key";
private static final String CARD_COUNT_KEY = "card_count_key";
private static final String CREATURE_TYPES_CACHE_OBJECT_NAME = "creature_types";
private static final String CREATURE_TYPES_KEY = "creature_types_key";
private static final String NONLAND_NAMES_CACHE_OBJECT_NAME = "nonland_names";
private static final String NONLAND_NAMES_KEY = "nonland_names_key";
private static final int CACHE_VERSION = 1;
public static Set<String> loadCardNames(List<Card> cards) {
Cache cache = CacheDataHelper.getCachedObject(NAMES_CACHE_OBJECT_NAME);
Set<String> names = new TreeSet<String>();
if (!CacheDataHelper.validateCache(cache, CACHE_VERSION, cards.size(), CARD_COUNT_KEY)) {
for (Card card : cards) {
names.add(card.getName());
}
cache = new Cache(NAMES_CACHE_OBJECT_NAME, CACHE_VERSION);
cache.getCacheObjects().put(NAMES_KEY, names);
cache.getCacheObjects().put(CARD_COUNT_KEY, cards.size());
CacheDataHelper.cacheObject(cache, NAMES_CACHE_OBJECT_NAME);
} else {
Set<String> cachedNames = (Set<String>) cache.getCacheObjects().get(NAMES_KEY);
names.addAll(cachedNames);
log.debug("Loaded card names from cache.");
}
return names;
}
public static Set<String> loadCreatureTypes(List<Card> cards) {
Set<String> creatureTypes = new TreeSet<String>();
Cache cache = CacheDataHelper.getCachedObject(CREATURE_TYPES_CACHE_OBJECT_NAME);
if (!CacheDataHelper.validateCache(cache, CACHE_VERSION, cards.size(), CARD_COUNT_KEY)) {
for (Card card : cards) {
if (card.getCardType().contains(Constants.CardType.CREATURE)) {
for (String type : card.getSubtype()) {
creatureTypes.add(type);
if (type.equals("")) {
throw new IllegalStateException("Card with empty subtype: " + card.getName());
}
}
}
}
cache = new Cache(CREATURE_TYPES_CACHE_OBJECT_NAME, CACHE_VERSION);
cache.getCacheObjects().put(CREATURE_TYPES_KEY, creatureTypes);
cache.getCacheObjects().put(CARD_COUNT_KEY, cards.size());
CacheDataHelper.cacheObject(cache, CREATURE_TYPES_CACHE_OBJECT_NAME);
} else {
Set<String> cachedCreatureTypes = (Set<String>) cache.getCacheObjects().get(CREATURE_TYPES_KEY);
creatureTypes.addAll(cachedCreatureTypes);
log.debug("Loaded creature types from cache.");
}
return creatureTypes;
}
public static Set<String> loadNonLandNames(List<Card> cards) {
Set<String> nonLandNames = new TreeSet<String>();
Cache cache = CacheDataHelper.getCachedObject(NONLAND_NAMES_CACHE_OBJECT_NAME);
if (!CacheDataHelper.validateCache(cache, CACHE_VERSION, cards.size(), CARD_COUNT_KEY)) {
for (Card card : cards) {
if (!card.getCardType().contains(Constants.CardType.LAND)) nonLandNames.add(card.getName());
}
cache = new Cache(NONLAND_NAMES_CACHE_OBJECT_NAME, CACHE_VERSION);
cache.getCacheObjects().put(NONLAND_NAMES_KEY, nonLandNames);
cache.getCacheObjects().put(CARD_COUNT_KEY, cards.size());
CacheDataHelper.cacheObject(cache, NONLAND_NAMES_CACHE_OBJECT_NAME);
} else {
Set<String> cachedNonLandNames = (Set<String>) cache.getCacheObjects().get(NONLAND_NAMES_KEY);
nonLandNames.addAll(cachedNonLandNames);
log.debug("Loaded non land names from cache.");
}
return nonLandNames;
}
}

View file

@ -14,10 +14,13 @@ import java.util.Set;
*/
public class CacheTest {
/**
* In case this test fails, it does mean that you need to update cache version in Sets.java
*/
@Test
public void testCacheConsistency() {
//Set<String> names = Sets.getCardNames();
//Set<String> nonLandNames = Sets.getNonLandCardNames();
Set<String> names = Sets.getCardNames();
Set<String> nonLandNames = Sets.getNonLandCardNames();
Set<String> creatureTypes = Sets.getCreatureTypes();
for (ExpansionSet set : Sets.getInstance().values()) {
@ -29,6 +32,14 @@ public class CacheTest {
}
}
}
if (!names.contains(card.getName())) {
Assert.assertTrue("Couldn't find a card name in the cache: " + card.getName(), false);
}
if (!card.getCardType().contains(Constants.CardType.LAND)) {
if (!nonLandNames.contains(card.getName())) {
Assert.assertTrue("Couldn't find a non-land card name in the cache: " + card.getName(), false);
}
}
}
}
}

View file

@ -31,8 +31,7 @@ package mage.sets;
import mage.Constants.CardType;
import mage.Constants.ColoredManaSymbol;
import mage.Mana;
import mage.cache.Cache;
import mage.cache.CacheDataHelper;
import mage.cache.CacheService;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.ExpansionSet;
@ -60,15 +59,6 @@ public class Sets extends HashMap<String, ExpansionSet> {
private static Map<String, Card> cardMap;
protected static Random rnd = new Random();
private static final String NAMES_CACHE_OBJECT_NAME = "card_names";
private static final String NAMES_KEY = "card_names_key";
private static final String CREATURE_TYPES_CACHE_OBJECT_NAME = "creature_types";
private static final String CREATURE_TYPES_KEY = "creature_types_key";
private static final String NONLAND_NAMES_CACHE_OBJECT_NAME = "nonland_names";
private static final String NONLAND_NAMES_KEY = "nonland_names_key";
private static final int CACHE_VERSION = 1;
public static Sets getInstance() {
return fINSTANCE;
}
@ -127,135 +117,29 @@ public class Sets extends HashMap<String, ExpansionSet> {
this.addSet(Weatherlight.getInstance());
this.addSet(Worldwake.getInstance());
this.addSet(Zendikar.getInstance());
loadCardNames();
loadCreatureTypes();
loadNonLandNames();
names = CacheService.loadCardNames(cards);
creatureTypes = CacheService.loadCreatureTypes(cards);
nonLandNames = CacheService.loadNonLandNames(cards);
}
private void addSet(ExpansionSet set) {
this.put(set.getCode(), set);
cards.addAll(set.getCards());
/*
for (Card card : set.getCards()) {
names.add(card.getName());
if (card.getCardType().contains(CardType.CREATURE)) {
for (String type : card.getSubtype()) {
creatureTypes.add(type);
if (type.equals("")) {
throw new IllegalStateException("Card with empty subtype: " + card.getName());
}
}
}
if (!card.getCardType().contains(CardType.LAND)) nonLandNames.add(card.getName());
}
if (creatureTypes.contains("")) {
creatureTypes.remove("");
}*/
}
private void loadCardNames() {
Cache cache = CacheDataHelper.getCachedObject(NAMES_CACHE_OBJECT_NAME);
if (cache == null || cache.getVersion() != CACHE_VERSION) {
for (Card card : cards) {
names.add(card.getName());
}
cache = new Cache(NAMES_CACHE_OBJECT_NAME, CACHE_VERSION);
cache.getCacheObjects().put(NAMES_KEY, names);
CacheDataHelper.cacheObject(cache, NAMES_CACHE_OBJECT_NAME);
} else {
Set<String> cachedNames = (Set<String>) cache.getCacheObjects().get(NAMES_KEY);
names.addAll(cachedNames);
}
}
private void loadCreatureTypes() {
Cache cache = CacheDataHelper.getCachedObject(CREATURE_TYPES_CACHE_OBJECT_NAME);
if (cache == null || cache.getVersion() != CACHE_VERSION) {
for (Card card : cards) {
if (card.getCardType().contains(CardType.CREATURE)) {
for (String type : card.getSubtype()) {
creatureTypes.add(type);
if (type.equals("")) {
throw new IllegalStateException("Card with empty subtype: " + card.getName());
}
}
}
}
cache = new Cache(CREATURE_TYPES_CACHE_OBJECT_NAME, CACHE_VERSION);
cache.getCacheObjects().put(CREATURE_TYPES_KEY, creatureTypes);
CacheDataHelper.cacheObject(cache, CREATURE_TYPES_CACHE_OBJECT_NAME);
} else {
Set<String> cachedCreatureTypes = (Set<String>) cache.getCacheObjects().get(CREATURE_TYPES_KEY);
creatureTypes.addAll(cachedCreatureTypes);
}
}
private void loadNonLandNames() {
Cache cache = CacheDataHelper.getCachedObject(NONLAND_NAMES_CACHE_OBJECT_NAME);
if (cache == null || cache.getVersion() != CACHE_VERSION) {
for (Card card : cards) {
if (!card.getCardType().contains(CardType.LAND)) nonLandNames.add(card.getName());
}
cache = new Cache(NONLAND_NAMES_CACHE_OBJECT_NAME, CACHE_VERSION);
cache.getCacheObjects().put(NONLAND_NAMES_KEY, nonLandNames);
CacheDataHelper.cacheObject(cache, NONLAND_NAMES_CACHE_OBJECT_NAME);
} else {
Set<String> cachedNonLandNames = (Set<String>) cache.getCacheObjects().get(NONLAND_NAMES_KEY);
nonLandNames.addAll(cachedNonLandNames);
}
}
/*private static void loadCards() {
if (cards.isEmpty()) {
System.out.println("Loading cards...");
long t1 = System.currentTimeMillis();
for (ExpansionSet set : getInstance().values()) {
cards.addAll(set.getCards());
for (Card card : set.getCards()) {
names.add(card.getName());
if (card.getCardType().contains(CardType.CREATURE)) {
for (String type : card.getSubtype()) {
creatureTypes.add(type);
if (type.equals("")) {
throw new IllegalStateException("Card with empty subtype: " + card.getName());
}
}
}
if (!card.getCardType().contains(CardType.LAND)) nonLandNames.add(card.getName());
}
}
if (creatureTypes.contains("")) {
creatureTypes.remove("");
}
System.out.println("It took " + (System.currentTimeMillis() - t1) / 1000 + " ms to load all cards.");
}
}*/
public static Set<String> getCardNames() {
/*if (names.isEmpty()) {
loadCards();
}*/
return names;
}
public static Set<String> getNonLandCardNames() {
/*if (nonLandNames.isEmpty()) {
loadCards();
}*/
return nonLandNames;
}
public static Set<String> getCreatureTypes() {
/*if (creatureTypes.isEmpty()) {
loadCards();
}*/
return creatureTypes;
}
public static Card getRandomCard() {
/*if (cards.isEmpty()) {
loadCards();
}*/
return cards.get(rnd.nextInt(cards.size()));
}