Collection serialization.

This commit is contained in:
marcins78@gmail.com
2011-09-21 17:35:28 +00:00
parent 83386a5646
commit bdafbf4d2a
8 changed files with 251 additions and 61 deletions

View File

@@ -3,7 +3,6 @@ package com.gempukku.lotro.cards.packs;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
@@ -12,28 +11,32 @@ import java.util.Map;
public class RarityReader {
public SetRarity getSetRarity(String setNo) {
try {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(RarityReader.class.getResourceAsStream("/set"+setNo+"-rarity.txt"), "UTF-8"));
String line;
List<String> tengwar = new LinkedList<String>();
Map<String, List<String>> cardsByRarity = new HashMap<String, List<String>>();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(RarityReader.class.getResourceAsStream("/set" + setNo + "-rarity.txt"), "UTF-8"));
try {
String line;
List<String> tengwar = new LinkedList<String>();
Map<String, List<String>> cardsByRarity = new HashMap<String, List<String>>();
while ((line = bufferedReader.readLine()) != null) {
if (line.endsWith("T"))
tengwar.add(line);
else {
if (!line.substring(0, setNo.length()).equals(setNo))
throw new IllegalStateException("Seems the rarity is for some other set");
String rarity = line.substring(setNo.length(), setNo.length()+1);
List<String> cards = cardsByRarity.get(rarity);
if (cards == null) {
cards = new LinkedList<String>();
cardsByRarity.put(rarity, cards);
while ((line = bufferedReader.readLine()) != null) {
if (line.endsWith("T"))
tengwar.add(line);
else {
if (!line.substring(0, setNo.length()).equals(setNo))
throw new IllegalStateException("Seems the rarity is for some other set");
String rarity = line.substring(setNo.length(), setNo.length() + 1);
List<String> cards = cardsByRarity.get(rarity);
if (cards == null) {
cards = new LinkedList<String>();
cardsByRarity.put(rarity, cards);
}
cards.add(line);
}
cards.add(line);
}
}
return new DefaultSetRarity(tengwar, cardsByRarity);
return new DefaultSetRarity(tengwar, cardsByRarity);
} finally {
bufferedReader.close();
}
} catch (IOException exp) {
throw new RuntimeException("Problem loading rarity of set " + setNo, exp);
}

View File

@@ -39,7 +39,7 @@
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.2</version>
<version>4.9</version>
<scope>test</scope>
</dependency>
</dependencies>

View File

@@ -0,0 +1,132 @@
package com.gempukku.lotro.collection;
import com.gempukku.lotro.game.CardCollection;
import com.gempukku.lotro.game.DefaultCardCollection;
import com.gempukku.lotro.game.LotroCardBlueprintLibrary;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class CollectionSerializer {
private List<String> _packIds = new ArrayList<String>();
private List<String> _cardIds = new ArrayList<String>();
private LotroCardBlueprintLibrary _library;
public CollectionSerializer(LotroCardBlueprintLibrary library) {
_library = library;
try {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(CollectionSerializer.class.getResourceAsStream("/packs.txt"), "UTF-8"));
try {
String line;
while ((line = bufferedReader.readLine()) != null)
_packIds.add(line);
} finally {
bufferedReader.close();
}
loadSet("1");
} catch (IOException exp) {
throw new RuntimeException("Problem loading collection data", exp);
}
}
private void loadSet(String setNo) throws IOException {
BufferedReader cardReader = new BufferedReader(new InputStreamReader(CollectionSerializer.class.getResourceAsStream("/set" + setNo + "-rarity.txt"), "UTF-8"));
try {
String line;
while ((line = cardReader.readLine()) != null) {
if (!line.substring(0, setNo.length()).equals(setNo))
throw new IllegalStateException("Seems the rarity is for some other set");
// Normal
_cardIds.add(translateToBlueprintId(line));
// Foil
_cardIds.add(translateToBlueprintId(line) + "*");
}
} finally {
cardReader.close();
}
}
private String translateToBlueprintId(String rarityString) {
int firstNonDigitIndex = getFirstNonDigitIndex(rarityString);
final String setNo = rarityString.substring(0, firstNonDigitIndex);
final String cardAfterSetNo = rarityString.substring(firstNonDigitIndex + 1);
return setNo + "_" + cardAfterSetNo;
}
private static int getFirstNonDigitIndex(String string) {
final char[] chars = string.toCharArray();
for (int i = 0; i < chars.length; i++)
if (!Character.isDigit(chars[i]))
return i;
return -1;
}
public void serializeCollection(CardCollection collection, OutputStream outputStream) throws IOException {
byte version = 0;
outputStream.write(version);
byte packBytes = (byte) _packIds.size();
outputStream.write(packBytes);
final Map<String, Integer> collectionCounts = collection.getAll();
for (String packId : _packIds) {
final Integer count = collectionCounts.get(packId);
if (count == null)
outputStream.write(0);
else
outputStream.write(count);
}
int cardBytes = _cardIds.size();
outputStream.write((cardBytes >> 8) & 0x000000ff);
outputStream.write(cardBytes & 0x000000ff);
for (String cardId : _cardIds) {
final Integer count = collectionCounts.get(cardId);
if (count == null)
outputStream.write(0);
else
outputStream.write(count);
}
}
public CardCollection deserializeCollection(InputStream inputStream) throws IOException {
int version = inputStream.read();
if (version == 0) {
return deserializeCollectionVer0(new BufferedInputStream(inputStream));
} else {
throw new IllegalStateException("Unkown version of serialized collection: " + version);
}
}
private CardCollection deserializeCollectionVer0(BufferedInputStream inputStream) throws IOException {
int packBytes = inputStream.read();
DefaultCardCollection collection = new DefaultCardCollection();
byte[] packs = new byte[packBytes];
int read = inputStream.read(packs);
if (read != packBytes)
throw new IllegalStateException("Under-read the packs information");
for (int i = 0; i < packs.length; i++)
if (packs[i] > 0)
collection.addPacks(_packIds.get(i), packs[i]);
int cardBytes = (inputStream.read() << 8) + inputStream.read();
byte[] cards = new byte[cardBytes];
read = inputStream.read(cards);
if (read != cardBytes)
throw new IllegalArgumentException("Under-read the packs information");
for (int i = 0; i < cards.length; i++)
if (cards[i] > 0) {
final String blueprintId = _cardIds.get(i);
collection.addCards(blueprintId, _library.getLotroCardBlueprint(blueprintId), cards[i]);
}
return collection;
}
}

View File

@@ -1,33 +0,0 @@
package com.gempukku.lotro.db.vo;
import java.util.List;
public class Deck {
private String _ringBearer;
private String _ring;
private List<String> _sites;
private List<String> _deck;
public Deck(String ringBearer, String ring, List<String> sites, List<String> deck) {
_ringBearer = ringBearer;
_ring = ring;
_sites = sites;
_deck = deck;
}
public String getRingBearer() {
return _ringBearer;
}
public String getRing() {
return _ring;
}
public List<String> getSites() {
return _sites;
}
public List<String> getDeck() {
return _deck;
}
}

View File

@@ -3,5 +3,7 @@ package com.gempukku.lotro.game;
import java.util.Map;
public interface CardCollection {
public Map<String, Integer> getAll();
public Map<String, Integer> filter(String filter);
}

View File

@@ -15,6 +15,15 @@ public class DefaultCardCollection implements CardCollection {
_cards.put(blueprintId, blueprint);
}
public void addPacks(String packId, int count) {
_cardsCount.put(packId, count);
}
@Override
public Map<String, Integer> getAll() {
return Collections.unmodifiableMap(_cardsCount);
}
@Override
public Map<String, Integer> filter(String filter) {
if (filter == null)
@@ -30,10 +39,10 @@ public class DefaultCardCollection implements CardCollection {
for (Map.Entry<String, LotroCardBlueprint> stringLotroCardBlueprintEntry : _cards.entrySet()) {
String blueprintId = stringLotroCardBlueprintEntry.getKey();
LotroCardBlueprint blueprint = stringLotroCardBlueprintEntry.getValue();
if (cardTypes == null || cardTypes.contains(blueprint.getCardType()))
if (cultures == null || cultures.contains(blueprint.getCulture()))
if (cardTypes == null || (blueprint != null && cardTypes.contains(blueprint.getCardType())))
if (cultures == null || (blueprint != null && cultures.contains(blueprint.getCulture())))
if (containsAllKeywords(blueprint, keywords))
if (siteNumber == null || blueprint.getSiteNumber() == siteNumber.intValue())
if (siteNumber == null || (blueprint != null && blueprint.getSiteNumber() == siteNumber.intValue()))
result.put(blueprintId, _cardsCount.get(blueprintId));
}
return result;
@@ -49,7 +58,7 @@ public class DefaultCardCollection implements CardCollection {
private boolean containsAllKeywords(LotroCardBlueprint blueprint, List<Keyword> keywords) {
for (Keyword keyword : keywords) {
if (!blueprint.hasKeyword(keyword))
if (blueprint == null || !blueprint.hasKeyword(keyword))
return false;
}
return true;
@@ -84,10 +93,43 @@ public class DefaultCardCollection implements CardCollection {
public int compare(String o1, String o2) {
String[] o1Parts = o1.split("_");
String[] o2Parts = o2.split("_");
if (o1Parts[0].equals(o2Parts[0]))
return Integer.parseInt(o1Parts[1]) - Integer.parseInt(o2Parts[1]);
else
return Integer.parseInt(o1Parts[0]) - Integer.parseInt(o2Parts[0]);
if (o1Parts[0].equals(o2Parts[0])) {
final int firstNumber = getAvailableNumber(o1Parts[1]);
final int secondNumber = getAvailableNumber(o2Parts[1]);
if (firstNumber != secondNumber)
return firstNumber - secondNumber;
return compareSameCardNumber(o1Parts[1], o2Parts[1]);
} else {
return getAvailableNumber(o1Parts[0]) - getAvailableNumber(o2Parts[0]);
}
}
private int compareSameCardNumber(String card1, String card2) {
if (card1.endsWith("*") && card2.endsWith("*"))
return compareNotFoils(card1.substring(0, card1.length() - 1), card2.substring(0, card2.length() - 1));
if (card1.endsWith("*"))
return -1;
if (card2.endsWith("*"))
return 1;
return compareNotFoils(card1, card2);
}
private int compareNotFoils(String card1, String card2) {
return card1.compareTo(card2);
}
private int getAvailableNumber(String str) {
return Integer.parseInt(str.substring(0, getFirstNonDigitIndex(str)));
}
private int getFirstNonDigitIndex(String str) {
final char[] chars = str.toCharArray();
for (int i = 0; i < chars.length; i++)
if (!Character.isDigit(chars[i]))
return i;
return chars.length;
}
}
}

View File

@@ -0,0 +1,2 @@
Fellowship of the Ring
FotR - League Starter

View File

@@ -0,0 +1,42 @@
package com.gempukku.lotro.collection;
import com.gempukku.lotro.game.CardCollection;
import com.gempukku.lotro.game.DefaultCardCollection;
import com.gempukku.lotro.game.LotroCardBlueprintLibrary;
import org.junit.Test;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Map;
import static junit.framework.Assert.assertEquals;
public class CollectionSerializerTest {
@Test
public void testSerializeDeserialize() throws IOException {
DefaultCardCollection collection = new DefaultCardCollection();
collection.addCards("1_1", null, 2);
collection.addCards("1_231T", null, 3);
collection.addCards("1_23*", null, 3);
collection.addCards("1_237T*", null, 3);
collection.addPacks("Fellowship of the Ring", 2);
CollectionSerializer serializer = new CollectionSerializer(new LotroCardBlueprintLibrary());
ByteArrayOutputStream baos = new ByteArrayOutputStream();
serializer.serializeCollection(collection, baos);
final byte[] bytes = baos.toByteArray();
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
CardCollection resultCollection = serializer.deserializeCollection(bais);
final Map<String, Integer> result = resultCollection.getAll();
assertEquals(5, result.size());
assertEquals(2, (int) result.get("1_1"));
assertEquals(3, (int) result.get("1_231T"));
assertEquals(3, (int) result.get("1_23*"));
assertEquals(3, (int) result.get("1_237T*"));
assertEquals(2, (int) result.get("Fellowship of the Ring"));
}
}