All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
za.co.knowles.pokewhat.domain.RoundBets Maven / Gradle / Ivy
package za.co.knowles.pokewhat.domain;
import za.co.knowles.pokewhat.domain.lookup.EBetResult;
import za.co.knowles.pokewhat.exceptions.ShouldNotHaveHappenedException;
import java.util.*;
import java.util.stream.Collectors;
public class RoundBets {
private final Map bets;
private final Map results = new HashMap<>();
private final List allInPlayers = new ArrayList<>();
private final List activePlayers;
private final List foldedPlayers = new ArrayList<>();
private final String potName;
private double currentBet;
private double totalBets;
private boolean allIn;
private int currentPlayerIndex;
public RoundBets(double blind, Player big, Player little, List activePlayers) {
this.potName = "Main";
this.bets = new HashMap<>();
this.activePlayers = activePlayers;
for (Player activePlayer : activePlayers) {
results.put(activePlayer, EBetResult.NOT_BETTED);
}
double bigBlind = 2 * blind;
playerBet(big, bigBlind);
results.put(big, EBetResult.BLIND);
playerBet(little, blind);
results.put(little, EBetResult.BLIND);
totalBets = sumOfCurrentBets();
this.currentBet = bigBlind;
this.currentPlayerIndex = activePlayers.indexOf(little);
}
/**
* Constructor used when resolving all in bets
*
* @param newBets the list of new bets taken from breaking an existing betting round down into smaller all-in chunks
* @param potName the description for the results
*/
public RoundBets(Map newBets, String potName) {
this.potName = potName;
this.activePlayers = new ArrayList<>(newBets.keySet());
this.bets = newBets;
this.totalBets = sumOfCurrentBets();
}
public Map getBets() {
return bets;
}
public RoundBets(List activeAfterRound, Player firstPlayer) {
this.potName = "Side";
this.bets = new HashMap<>();
this.activePlayers = activeAfterRound;
this.currentPlayerIndex = activeAfterRound.indexOf(firstPlayer);
for (Player activePlayer : activePlayers) {
results.put(activePlayer, EBetResult.NOT_BETTED);
}
}
private double sumOfCurrentBets() {
return bets.values().stream().mapToDouble(Double::doubleValue).sum();
}
public EBetResult placeBet(Player player, double bet) {
if (activePlayers.indexOf(player) != currentPlayerIndex) {
return EBetResult.OUT_OF_TURN;
}
boolean goingAllIn = bet >= player.getMoney();
bet = Math.min(bet, player.getMoney());
double playerTotal = bet + getPlayerBet(player);
if (!goingAllIn && playerTotal < currentBet) {
fold(player);
return EBetResult.FOLDED;
}
playerBet(player, bet);
advancePlayerIndex();
if (playerTotal >= currentBet && bet == 0) {
return playerResult(EBetResult.CHECKED, player);
}
if (playerTotal == currentBet) {
return playerResult(goingAllIn ? EBetResult.ALL_IN : EBetResult.SAW, player);
}
if (playerTotal > currentBet) {
currentBet = playerTotal;
return playerResult(goingAllIn ? EBetResult.ALL_IN : EBetResult.RAISED, player);
}
throw new ShouldNotHaveHappenedException("Player total was unlike the bet in any way.");
}
private void advancePlayerIndex() {
Player nextPlayer = null;
int startingIndex = currentPlayerIndex;
boolean first = true;
while ((startingIndex != currentPlayerIndex || first) && (nextPlayer == null || (results.get(nextPlayer) != null && results.get(nextPlayer).isOutOfGame()))) {
first = false;
currentPlayerIndex = (currentPlayerIndex + 1) % activePlayers.size();
nextPlayer = activePlayers.get(currentPlayerIndex);
}
}
/**
* Special fold for special occasions like the player leaving the game
*/
public void fold(Player player) {
results.put(player, EBetResult.FOLDED);
foldedPlayers.add(player);
if (getCurrentPlayer() == player) {
advancePlayerIndex();
}
}
private void playerBet(Player player, double bet) {
player.loseMoney(bet);
double entireBet = bet + getPlayerBet(player);
bets.put(player, entireBet);
totalBets += bet;
}
private Double getPlayerBet(Player player) {
if (!bets.containsKey(player)) {
return 0d;
}
return bets.get(player);
}
public boolean isRoundDone() {
if (allIn) {
return true;
}
List bettingPlayers = activePlayers.stream().filter(a -> results.get(a) != EBetResult.FOLDED).collect(Collectors.toList());
if (bettingPlayers.size() == 1) {
return true;
}
for (Player bettingPlayer : bettingPlayers) {
EBetResult playerResult = results.get(bettingPlayer);
if (playerResult == EBetResult.NOT_BETTED || playerResult == EBetResult.BLIND || (playerResult != EBetResult.ALL_IN && bets.get(bettingPlayer) < currentBet)) {
return false;
}
}
return true;
}
private List getBettingPlayers() {
return activePlayers.stream().filter(a -> !results.get(a).isOutOfGame()).collect(Collectors.toList());
}
public List getInGamePlayers() {
ArrayList players = new ArrayList<>(activePlayers);
players.removeAll(foldedPlayers);
return players;
}
private EBetResult playerResult(EBetResult result, Player player) {
results.put(player, result);
return result;
}
public void next(Player nextPlayer) {
if (!isRoundDone()) {
return;
}
Set foldedPlayers = new HashSet<>();
for (Player player : results.keySet()) {
EBetResult result = results.get(player);
if (result != EBetResult.FOLDED) {
if (result == EBetResult.ALL_IN) {
allInPlayers.add(player);
}
} else {
foldedPlayers.add(player);
}
}
if (results.containsValue(EBetResult.ALL_IN)) {
allIn = true;
}
List bettingPlayers = getBettingPlayers();
results.clear();
currentBet = 0;
for (Player foldedPlayer : foldedPlayers) {
results.put(foldedPlayer, EBetResult.FOLDED);
}
for (Player foldedPlayer : allInPlayers) {
results.put(foldedPlayer, EBetResult.ALL_IN);
}
for (Player bettingPlayer : bettingPlayers) {
results.put(bettingPlayer, EBetResult.NOT_BETTED);
}
if (nextPlayer != null) {
currentPlayerIndex = activePlayers.indexOf(nextPlayer);
}
}
public double getTotalBetPool() {
return totalBets;
}
public boolean isAllIn() {
return allIn;
}
public List getActiveAfterRound() {
return getBettingPlayers();
}
public Player getCurrentPlayer() {
return activePlayers.get(currentPlayerIndex);
}
public String getDescription() {
return potName;
}
public List normalize() {
if (!isRoundDone() || this.allInPlayers.size() <= 1) {
return Collections.singletonList(this);
}
List resultingBets = new ArrayList<>();
List activePlayers = new ArrayList<>(this.activePlayers);
Map> collect = this.allInPlayers.stream().collect(Collectors.groupingBy(bets::get));
ArrayList allInBets = new ArrayList<>(collect.keySet());
allInBets.sort(Double::compareTo);
while (allInBets.size() > 1) {
Map newBets = new HashMap<>();
Double current = allInBets.remove(0);
for (Player activePlayer : activePlayers) {
newBets.put(activePlayer, current);
}
resultingBets.add(new RoundBets(newBets, resultingBets.isEmpty() ? "Main" : "Side"));
for (Player activePlayer : activePlayers) {
if (collect.get(current).contains(activePlayer)) {
bets.remove(activePlayer);
} else {
bets.put(activePlayer, bets.get(activePlayer) - current);
}
}
}
resultingBets.add(new RoundBets(bets, "Side"));
return resultingBets;
}
public double getCurrentBet() {
return currentBet;
}
}