com.cubeia.games.poker.handler.ActionTransformer.java Source code

Java tutorial

Introduction

Here is the source code for com.cubeia.games.poker.handler.ActionTransformer.java

Source

/**
 * Copyright (C) 2010 Cubeia Ltd <info@cubeia.com>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.cubeia.games.poker.handler;

import com.cubeia.firebase.api.action.GameDataAction;
import com.cubeia.games.poker.common.money.Currency;
import com.cubeia.games.poker.io.protocol.*;
import com.cubeia.games.poker.io.protocol.Enums.ActionType;
import com.cubeia.games.poker.io.protocol.Enums.PotType;
import com.cubeia.games.poker.io.protocol.Enums.Rank;
import com.cubeia.games.poker.io.protocol.Enums.Suit;
import com.cubeia.games.poker.util.ProtocolFactory;
import com.cubeia.poker.action.*;
import com.cubeia.poker.hand.Card;
import com.cubeia.poker.hand.ExposeCardsHolder;
import com.cubeia.poker.hand.ExposedCards;
import com.cubeia.poker.hand.HandType;
import com.cubeia.poker.model.RatedPlayerHand;
import com.cubeia.poker.player.PokerPlayer;
import com.cubeia.poker.pot.PotTransition;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Range;
import com.google.common.primitives.Ints;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;

import static com.cubeia.games.poker.io.protocol.Enums.ActionType.DISCARD;

/**
 * Translates poker-logic internal actions to the styx wire-protocol
 * as defined in poker-protocol.
 *
 * @author Fredrik Johansson, Cubeia Ltd
 */
public class ActionTransformer {

    private final Logger log = LoggerFactory.getLogger(getClass());

    public RequestAction transform(ActionRequest request, int sequenceNumber) {
        RequestAction packet = new RequestAction();
        packet.timeToAct = (int) request.getTimeToAct();
        packet.player = request.getPlayerId();
        packet.seq = sequenceNumber;
        packet.currentPotSize = request.getTotalPotSize().toPlainString();

        List<PlayerAction> allowed = new LinkedList<PlayerAction>();
        for (PossibleAction option : request.getOptions()) {
            if (option instanceof DiscardRequest) {
                DiscardRequest discardRequest = (DiscardRequest) option;
                PlayerAction playerOption = createPlayerAction(PokerActionType.DISCARD);
                Range<Integer> cardsToDiscard = discardRequest.getCardsToDiscard();
                // TODO: Consider if this is an ugly hack or if it's OK. (Using minAmount and maxAmount to describe the range of number of cards to discard)
                playerOption.minAmount = cardsToDiscard.lowerEndpoint().toString();
                playerOption.maxAmount = cardsToDiscard.upperEndpoint().toString();
                allowed.add(playerOption);
            } else {
                PlayerAction playerOption = createPlayerAction(option.getActionType());
                // FIXME: Casting to integer here since Flash does not support long values!
                playerOption.minAmount = option.getMinAmount().toPlainString();
                playerOption.maxAmount = option.getMaxAmount().toPlainString();
                allowed.add(playerOption);
            }
        }
        packet.allowedActions = allowed;

        return packet;
    }

    public PerformAction transform(PokerAction pokerAction, PokerPlayer pokerPlayer) {
        PerformAction packet = new PerformAction();
        packet.action = createPlayerAction(pokerAction.getActionType());
        packet.betAmount = pokerAction.getBetAmount().toPlainString();
        packet.raiseAmount = pokerAction.getRaiseAmount().toPlainString();
        packet.stackAmount = pokerPlayer.getBetStack().toPlainString();
        packet.player = pokerAction.getPlayerId();
        packet.timeout = pokerAction.isTimeout();
        return packet;
    }

    public PokerActionType transform(ActionType actionType) {
        return PokerActionType.valueOf(actionType.name());
    }

    public PokerAction transform(int playerId, PerformAction packet, Currency currency) {
        ActionType actionType = packet.action.type;
        if (actionType == DISCARD) {
            return convertDiscardAction(playerId, packet);
        } else {
            PokerAction converted = new PokerAction(playerId, transform(actionType));
            converted.setBetAmount(transformAmount(packet.betAmount, currency));
            return converted;
        }
    }

    private BigDecimal transformAmount(String amount, Currency c) {
        BigDecimal transformedAmount = BigDecimal.ZERO;
        try {
            transformedAmount = new BigDecimal(amount).setScale(c.getFractionalDigits(), RoundingMode.DOWN);
        } catch (NumberFormatException e) {
            log.debug("Unable to transform amount in PokerAction " + amount);
        }
        return transformedAmount;
    }

    private PokerAction convertDiscardAction(int playerId, PerformAction action) {
        return new DiscardAction(playerId, Ints.asList(action.cardsToDiscard));
    }

    @VisibleForTesting
    protected PlayerAction createPlayerAction(PokerActionType actionType) {
        PlayerAction action = new PlayerAction();
        action.type = fromPokerActionTypeToProtocolActionType(actionType);

        return action;
    }

    public ActionType fromPokerActionTypeToProtocolActionType(PokerActionType actionType) {
        return ActionType.valueOf(actionType.name());
    }

    /**
     * @param playerId, the player receiving the cards
     * @param cards,    the cards to be dealt
     * @param hidden,   true if the suit and rank should be of type HIDDEN only
     */
    public DealPrivateCards createPrivateCardsPacket(int playerId, List<Card> cards, boolean hidden) {
        DealPrivateCards packet = new DealPrivateCards();
        packet.cards = new LinkedList<CardToDeal>();
        for (Card card : cards) {
            GameCard gCard = new GameCard();
            gCard.cardId = card.getId();

            if (!hidden) {
                gCard.rank = convertRankToProtocolEnum(card.getRank());
                gCard.suit = convertSuitToProtocolEnum(card.getSuit());
            } else {
                gCard.rank = Enums.Rank.HIDDEN;
                gCard.suit = Enums.Suit.HIDDEN;
            }

            CardToDeal deal = new CardToDeal();
            deal.player = playerId;
            deal.card = gCard;
            packet.cards.add(deal);
        }
        return packet;
    }

    public Rank convertRankToProtocolEnum(com.cubeia.poker.hand.Rank rank) {
        return Enums.Rank.values()[rank.ordinal()];
    }

    public Suit convertSuitToProtocolEnum(com.cubeia.poker.hand.Suit suit) {
        return Enums.Suit.values()[suit.ordinal()];
    }

    public Enums.HandType convertHandTypeToEnum(HandType handType) {
        return Enums.HandType.values()[handType.ordinal()];
    }

    public DealPublicCards createPublicCardsPacket(List<Card> cards) {
        DealPublicCards packet = new DealPublicCards();
        packet.cards = new LinkedList<GameCard>();
        for (Card card : cards) {
            GameCard gCard = new GameCard();

            gCard.rank = Enums.Rank.values()[card.getRank().ordinal()];
            gCard.suit = Enums.Suit.values()[card.getSuit().ordinal()];
            gCard.cardId = card.getId();

            packet.cards.add(gCard);
        }
        return packet;
    }

    public Card convertGameCard(GameCard c) {
        return new Card(c.cardId, com.cubeia.poker.hand.Rank.values()[c.rank.ordinal()],
                com.cubeia.poker.hand.Suit.values()[c.suit.ordinal()]);
    }

    public ExposePrivateCards createExposeCardsPacket(ExposeCardsHolder holder) {
        ExposePrivateCards packet = new ExposePrivateCards();
        packet.cards = new LinkedList<CardToDeal>();
        for (ExposedCards exposedCards : holder.getExposedCards()) {
            Collection<Card> cards = exposedCards.getCards();
            for (Card card : cards) {
                GameCard gCard = new GameCard();
                gCard.rank = Enums.Rank.values()[card.getRank().ordinal()];
                gCard.suit = Enums.Suit.values()[card.getSuit().ordinal()];
                gCard.cardId = card.getId();

                CardToDeal deal = new CardToDeal(exposedCards.getPlayerId(), gCard);
                packet.cards.add(deal);
            }
        }
        return packet;
    }

    public BestHand createBestHandPacket(int playerId, HandType handType, List<Card> cardsInHand) {
        List<GameCard> gameCards = convertCards(cardsInHand);

        return new BestHand(playerId, convertHandTypeToEnum(handType), gameCards);
    }

    @VisibleForTesting
    protected List<GameCard> convertCards(List<Card> cardsInHand) {
        List<GameCard> gameCards = new ArrayList<GameCard>();
        for (Card c : cardsInHand) {
            gameCards.add(new GameCard(c.getId(), convertSuitToProtocolEnum(c.getSuit()),
                    convertRankToProtocolEnum(c.getRank())));
        }
        return gameCards;
    }

    public HandEnd createHandEndPacket(Collection<RatedPlayerHand> hands, PotTransfers potTransfers,
            List<Integer> playerIdRevealOrder) {
        HandEnd packet = new HandEnd();
        packet.hands = new LinkedList<BestHand>();

        for (RatedPlayerHand ratedHand : hands) {
            List<GameCard> cards = new ArrayList<GameCard>();

            for (Card card : ratedHand.getBestHandCards()) {
                cards.add(new GameCard(card.getId() == null ? -1 : card.getId(),
                        convertSuitToProtocolEnum(card.getSuit()), convertRankToProtocolEnum(card.getRank())));
            }

            BestHand best = new BestHand(ratedHand.getPlayerId(),
                    convertHandTypeToEnum(ratedHand.getHandInfo().getHandType()), cards);

            packet.hands.add(best);
        }

        packet.potTransfers = potTransfers;

        int[] playerIdRevealOrderArray = new int[playerIdRevealOrder.size()];
        int index = 0;
        for (Integer playerId : playerIdRevealOrder) {
            playerIdRevealOrderArray[index++] = playerId;
        }
        packet.playerIdRevealOrder = playerIdRevealOrderArray;

        return packet;
    }

    public Pot createPotUpdatePacket(int id, BigDecimal amount) {
        Pot packet = new Pot();
        packet.amount = amount.toPlainString();
        packet.id = (byte) id;
        packet.type = id == 0 ? PotType.MAIN : PotType.SIDE;
        return packet;
    }

    public GameDataAction createPlayerBalanceAction(BigDecimal balance, BigDecimal pendingBalance,
            BigDecimal playersContributionToPot, int playerId, int tableId) {
        PlayerBalance packet = new PlayerBalance(balance.toPlainString(), pendingBalance.toPlainString(), playerId,
                playersContributionToPot.toPlainString());
        return new ProtocolFactory().createGameAction(packet, playerId, tableId);
    }

    public PotTransfer createPotTransferPacket(PotTransition potTransition) {
        return new PotTransfer((byte) potTransition.getPot().getId(), potTransition.getPlayer().getId(),
                potTransition.getAmount().toPlainString());
    }
}