package com.barcicki.trio.core;
import java.util.EnumSet;
import android.util.Log;
public class Trio {
public static int MAX_CARDS = 81;
public static int DEFUALT_TABLE_SIZE = 12;
public static int DEFAULT_TABLE_ADDON = 1;
public enum TrioStatus {
EXISTS,
NOT_3_CARDS,
WRONG_SHAPE,
WRONG_COLOR,
WRONG_FILL,
WRONG_NUMBER
}
public static boolean LOCAL_LOGD = false;
public static boolean LOCAL_LOGV = false;
private CardList mDeck;
private CardList mGame;
private String mGameString;
private CardList mTable;
public Trio() {
generateCards();
}
/*
* Setters and getters
*/
public CardList getDeck() {
if (null == mDeck) this.mDeck = new CardList();
return mDeck;
}
public void setDeck(CardList cards) {
this.mDeck = cards;
}
public CardList getGame() {
if (null == mGame) this.mGame = getDeck();
return mGame;
}
public void setGame(CardList game) {
this.mGame = game;
}
public String getGameString() {
return mGameString;
}
public void setGameString(String gameString) {
this.mGameString = gameString;
}
/*
* Game logic
*/
/**
* Starts new game
*/
public void newGame() {
mDeck.shuffle();
mGame = new CardList(mDeck);
mGameString = mGame.toString();
mTable = new CardList();
updateTable();
}
/**
* Resets game progress.
*/
public void restartGame(String gameString) {
mGame = CardList.fromString(mDeck, gameString);
mTable = new CardList();
updateTable();
}
/**
* Updates table deck of cards so it have at least DEFAULT_TABLE_SIZE cards and at least one Trio
*/
public void updateTable() {
if (getGame().size() > 0) {
// if empty, create new set of 12 cards
if (getTable().size() <= 0) {
mTable = new CardList(getGame().getNext(DEFUALT_TABLE_SIZE));
}
//
if (getTable().size() < DEFUALT_TABLE_SIZE) {
int missing = DEFUALT_TABLE_SIZE - getTable().size();
if (missing > getGame().size()) {
missing = getGame().size();
}
if (missing > 0) {
getTable().addAll(getGame().getNext(missing));
if (LOCAL_LOGV) Log.v("Table", "Table replenished to DEFAULT number");
} else {
if (LOCAL_LOGV) Log.v("Table", "No more cards to replenish");
}
}
} else {
if (LOCAL_LOGD) Log.d("Game Deck", "Game Deck is empty");
}
while (!getTable().hasTrio() && getGame().size() > 0) {
getTable().addAll(getGame().getNext(DEFAULT_TABLE_ADDON));
if (LOCAL_LOGV) Log.v("Table", "Added additional cards");
}
if (LOCAL_LOGV) Log.v("Table", "Table prepared");
}
public CardList getTable() {
if (null == mTable) mTable = new CardList();
return mTable;
}
public void setTable(CardList table) {
this.mTable = table;
}
/**
* Assuming that trio was found, given cards are removed from table deck
* @param trio Set of cards that make trio
* @return New table set
*/
public CardList foundTrio(CardList trio) {
getTable().removeAll(trio);
updateTable();
return getTable();
}
/**
* Shuffles the deck
*/
public void shuffle() {
getDeck().shuffle();
if (LOCAL_LOGV) Log.v("Deck", "Deck shuffled");
}
/**
* Checks if set consisting of three cards make trio
* @param cards Set of cards
* @return True if cards make trio
*/
public static boolean isTrio(CardList cards) {
if (cards.size() == 3) {
return isTrio(cards.get(0), cards.get(1), cards.get(2));
}
return false;
}
/**
* Checks if given cards make trio
* @param cardA
* @param cardB
* @param cardC
* @return True if cards make trio
*/
public static boolean isTrio(Card cardA, Card cardB, Card cardC) {
if ((cardA.getShape() + cardB.getShape() + cardC.getShape()) % 3 != 0) return false;
if ((cardA.getColor() + cardB.getColor() + cardC.getColor()) % 3 != 0) return false;
if ((cardA.getFill() + cardB.getFill() + cardC.getFill()) % 3 != 0) return false;
if ((cardA.getNumber() + cardB.getNumber() + cardC.getNumber()) % 3 != 0) return false;
return true;
}
public CardList getSetWithTrios(int numberOfTrios) {
CardList set = new CardList(getDeck());
CardList table;
do {
table = set.getRandomRange(DEFUALT_TABLE_SIZE);
} while (table.numberOfTrios() != numberOfTrios);
return table;
}
public static Card getTrioCard(Card cardA, Card cardB) {
int sum_shape = (3 - (cardA.getShape() + cardB.getShape()) % 3) % 3;
int sum_color = (3 - (cardA.getColor() + cardB.getColor()) % 3) % 3;
int sum_number = (3 - (cardA.getNumber() + cardB.getNumber()) % 3) % 3;
int sum_fill = (3 - (cardA.getFill() + cardB.getFill()) % 3) % 3;
return new Card(sum_shape, sum_color, sum_fill, sum_number);
}
public static EnumSet<TrioStatus> getTrioStatus(CardList threeCards) {
if (threeCards.size() == 3) {
return getTrioStatus(threeCards.get(0), threeCards.get(1), threeCards.get(2));
} else {
EnumSet<TrioStatus> status = EnumSet.of(TrioStatus.NOT_3_CARDS);
return status;
}
}
public static EnumSet<TrioStatus> getTrioStatus(Card cardA, Card cardB, Card cardC) {
EnumSet<TrioStatus> status = EnumSet.noneOf(TrioStatus.class);
if ((cardA.getShape() + cardB.getShape() + cardC.getShape()) % 3 != 0) status.add(TrioStatus.WRONG_SHAPE);
if ((cardA.getColor() + cardB.getColor() + cardC.getColor()) % 3 != 0) status.add(TrioStatus.WRONG_COLOR);
if ((cardA.getFill() + cardB.getFill() + cardC.getFill()) % 3 != 0) status.add(TrioStatus.WRONG_FILL);
if ((cardA.getNumber() + cardB.getNumber() + cardC.getNumber()) % 3 != 0) status.add(TrioStatus.WRONG_NUMBER);
if (status.isEmpty()) status.add(TrioStatus.EXISTS);
return status;
}
/*
* Private methods
*/
/**
* Populates deck list with basic cards
*/
private void generateCards() {
for (int i = 0; i < MAX_CARDS; i++) {
getDeck().add(new Card( (i/27)%3, (i/9)%3, (i/3)%3, i%3 ));
}
if (LOCAL_LOGV) Log.v("Card Generator", "All cards have been generated");
}
}