package game.deck;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import com.biotools.meerkat.Card;
import com.biotools.meerkat.Hand;
/**
* A SerializedDeck just replays Cards which were recorded in
* advance.<br>
* {@link #main(String[])} creates a simple 100.000 Games Deck (with communitcards and 10players)<br>
* with {@link #serializeDeck(OutputStream, int, Deck)} one can create arbitrary new decks<br>
* <br>
* The format is quite easy:<br>
* Each game starts with a marker byte (=0), followed by 5 community cards, followed by 10*2 player cards.
* Cards are saved by their index.
*
*/
public class SerializedDeck implements Deck {
private InputStream deckStream;
// 5 community-cards + 10 playercards for each game
private byte[] currentHand = new byte[5 + 2 * 10];
private int numGames = 0;
/**
* @return a factory for SerializedDecks, all starting with the same file
*/
public static DeckFactory createFactory(final String deckFilename) {
return new DeckFactory() {
@Override
public Deck createDeck() {
try {
return new SerializedDeck(new FileInputStream(new File(deckFilename)));
} catch (FileNotFoundException e) {
throw new RuntimeException("Error creating SerializedDeck", e);
}
}
};
}
/**
* @param deckStream a stream with cards created by {@link #serializeDeck(OutputStream, int, Deck)}
*/
public SerializedDeck(InputStream deckStream) {
this.deckStream = deckStream;
}
@Override
public Card getCommunityCard(int communityCardNumber) {
return new Card(currentHand[communityCardNumber]);
}
@Override
public Hand getPlayerCards(int seat) {
Card c1 = new Card(currentHand[5 + seat * 2 + 0]);
Card c2 = new Card(currentHand[5 + seat * 2 + 1]);
Hand hand = new Hand();
hand.addCard(c1);
hand.addCard(c2);
return hand;
}
@Override
public void nextGame() {
numGames++;
try {
int marker = deckStream.read();
if (marker != 0) {
throw new IllegalStateException("Error reading from deck-file after " + numGames + " games: marker is not '0'");
}
deckStream.read(currentHand);
} catch (IOException e) {
throw new IllegalStateException("Error reading from deck-file after " + numGames + " games", e);
}
}
/**
* create a serialized Deck with the given number of cards.<br>
* @param outStream
* @param numCards
* @param deckGenerator another Deck to create the actual cards. Typically would be {@link RandomDeck}
* @throws IOException
*/
public static void serializeDeck(OutputStream outStream, int numCards, Deck deckGenerator) throws IOException {
for (int i = 0; i < numCards; i++) {
deckGenerator.nextGame();
byte[] outCards = new byte[5 + 2 * 10];
outCards[0] = (byte) deckGenerator.getCommunityCard(0).getIndex();
outCards[1] = (byte) deckGenerator.getCommunityCard(1).getIndex();
outCards[2] = (byte) deckGenerator.getCommunityCard(2).getIndex();
outCards[3] = (byte) deckGenerator.getCommunityCard(3).getIndex();
outCards[4] = (byte) deckGenerator.getCommunityCard(4).getIndex();
for (int player = 0; player < 10; player++) {
Hand playerHand = deckGenerator.getPlayerCards(player);
outCards[5 + player * 2 + 0] = (byte) playerHand.getFirstCard().getIndex();
outCards[5 + player * 2 + 1] = (byte) playerHand.getSecondCard().getIndex();
}
outStream.write(0); // marker
outStream.write(outCards);
}
}
/**
* writes a serialized deck with 100.000 games to ./data/decks
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
OutputStream out = new FileOutputStream("./data/decks/deck-100000.deck");
serializeDeck(out, 100000, new RandomDeck());
out.close();
}
}