package com.flexpoker.table.command.aggregate.pot;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
import com.flexpoker.exception.FlexPokerException;
import com.flexpoker.table.command.aggregate.HandEvaluation;
public class Pot {
private final UUID entityId;
private final Set<HandEvaluation> handEvaluations;
private final Set<UUID> playersInvolved;
private final Map<UUID, Integer> chipsForPlayerToWin;
private int amount;
private boolean open;
public Pot(UUID entityId, Set<HandEvaluation> handEvaluations) {
this.entityId = entityId;
this.handEvaluations = handEvaluations;
this.playersInvolved = handEvaluations.stream().map(x -> x.getPlayerId())
.collect(Collectors.toSet());
chipsForPlayerToWin = new HashMap<>();
open = true;
}
public UUID getId() {
return entityId;
}
public int getChipsWon(UUID playerInHand) {
return chipsForPlayerToWin.getOrDefault(playerInHand, Integer.valueOf(0))
.intValue();
}
public boolean forcePlayerToShowCards(UUID playerInHand) {
return getChipsWon(playerInHand) > 0 && playersInvolved.size() > 1;
}
public void addChips(int chips) {
if (!open) {
throw new FlexPokerException("cannot add chips to a closed pot");
}
amount += chips;
recalculateWinners();
}
public void removePlayer(UUID playerId) {
if (!open) {
throw new FlexPokerException("cannot remove player from a closed pot");
}
playersInvolved.remove(playerId);
handEvaluations.removeIf(x -> x.getPlayerId().equals(playerId));
recalculateWinners();
}
public boolean isOpen() {
return open;
}
public void closePot() {
open = false;
}
private void recalculateWinners() {
List<HandEvaluation> relevantHandEvaluationsForPot = handEvaluations.stream()
.filter(x -> playersInvolved.contains(x.getPlayerId()))
.sorted((x, y) -> y.compareTo(x))
.collect(Collectors.toList());
HandEvaluation topAssignedHand = null;
List<UUID> winners = new ArrayList<>();
for (HandEvaluation handEvaluation : relevantHandEvaluationsForPot) {
if (topAssignedHand == null || topAssignedHand.compareTo(handEvaluation) == 0) {
topAssignedHand = handEvaluation;
winners.add(topAssignedHand.getPlayerId());
}
}
int numberOfWinners = winners.size();
int baseNumberOfChips = amount / numberOfWinners;
int bonusChips = amount % numberOfWinners;
chipsForPlayerToWin.clear();
winners.forEach(x -> chipsForPlayerToWin.put(x, baseNumberOfChips));
if (bonusChips >= 1) {
int randomNumber = new Random(System.currentTimeMillis())
.nextInt(winners.size());
chipsForPlayerToWin.compute(winners.get(randomNumber),
(playerId, chips) -> chips + bonusChips);
}
}
}