/**
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package bots.mctsbot.ai.opponentmodels.weka;
/**
* Class that tracks player statistics when playing games.
*
* @author guy
*
*/
public class PlayerData implements Cloneable {
private final Object id;
private int bb;
private int stack;
private int bet;
private boolean comitted;
private boolean lastActionWasRaise;
private int gameCount = 0;
private int VPIPCount = 0;
private int PFRCount = 0;
private int flopCount = 0;
private int showdownCount = 0;
private BetStatistics gameStats = new BetStatistics();
private BetStatistics globalStats = new BetStatistics();
public PlayerData(Object id) {
this.id = id;
}
@Override
protected PlayerData clone() {
try {
PlayerData clone = (PlayerData) super.clone();
clone.gameStats = clone.gameStats.clone();
clone.globalStats = clone.globalStats.clone();
return clone;
} catch (CloneNotSupportedException e) {
throw new IllegalStateException(e);
}
}
public void signalBBAmount(int bb) {
this.bb = bb;
}
public Object getId() {
return id;
}
public int getStack() {
return stack;
}
public double getRelativeStack() {
return stack / (double) bb;
}
public int getBB() {
return bb;
}
public int getBet() {
return bet;
}
public double getRelativeBet() {
return bet / (double) bb;
}
public int getGameCount() {
return gameCount;
}
public BetStatistics getGameStats() {
return gameStats;
}
public BetStatistics getGlobalStats() {
return globalStats;
}
public int getDeficit(Propositionalizer p) {
return Math.min(stack, (p.getMaxBet() - bet));
}
public double getRelativeDeficit(Propositionalizer p) {
return getDeficit(p) / (double) bb;
}
public double getPotOdds(Propositionalizer p) {
int potSize = p.getPotSize();
int deficit = getDeficit(p);
return deficit / (double) (deficit + potSize);
}
// "@attribute VPIP real\n"+
public double getVPIP(int memory) {
return (0.3F * memory + VPIPCount) / (memory + gameCount);
}
// "@attribute PFR real\n"+
public double getPFR(int memory) {
return (0.16F * memory + PFRCount) / (memory + gameCount);
}
// "@attribute WtSD real\n"+
public double getWtSD(int memory) {
if (Math.random() < 0.00001) {
System.out.println();
System.out.println(showdownCount + " " + flopCount);
System.out.println("WtSD for " + id + " = " + ((0.57F * memory + showdownCount) / (memory + flopCount)));
}
return (0.57F * memory + showdownCount) / (memory + flopCount);
}
public boolean isComitted() {
return comitted;
}
public boolean isLastActionWasRaise() {
return lastActionWasRaise;
}
protected void startNewGame() {
didVPIP = false;
comitted = false;
lastActionWasRaise = false;
++gameCount;
gameStats = new BetStatistics();
startNewRound();
}
protected void startNewRound() {
bet = 0;
comitted = false;
}
protected boolean didVPIP = false;
protected void updateVPIP(Propositionalizer p) {
if (!didVPIP && p.inPreFlopRound()) {
++VPIPCount;
didVPIP = true;
}
}
protected void updatePFR(Propositionalizer p) {
if (p.inPreFlopRound() && gameStats.getNbBetsRaisesPreFlop() == 0) {
++PFRCount;
}
}
public void signalBet(Propositionalizer p, int amount) {
bet += amount;
decreaseStack(amount);
comitted = true;
lastActionWasRaise = true;
updateVPIP(p);
updatePFR(p); //before gameStats
gameStats.addBet(p, amount / (double) bb);
globalStats.addBet(p, amount / (double) bb);
}
private void decreaseStack(int amount) {
stack -= amount;
if (stack < 0) {
throw new IllegalStateException("Bad stack: " + stack + " when decreasing by " + amount);
}
}
public void signalCheck(Propositionalizer p) {
lastActionWasRaise = false;
gameStats.addCheck(p);
globalStats.addCheck(p);
}
public void signalRaise(Propositionalizer p, int raiseAmount, int movedAmount) {
bet += movedAmount;
decreaseStack(movedAmount);
updateVPIP(p);
updatePFR(p);
lastActionWasRaise = true;
comitted = true;
gameStats.addRaise(p, (movedAmount - raiseAmount) / (double) bb, raiseAmount / (double) bb);
globalStats.addRaise(p, (movedAmount - raiseAmount) / (double) bb, raiseAmount / (double) bb);
}
public void signalCall(Propositionalizer p, int movedAmount) {
bet += movedAmount;
decreaseStack(movedAmount);
lastActionWasRaise = false;
updateVPIP(p);
comitted = true;
gameStats.addCall(p, movedAmount / (double) bb);
globalStats.addCall(p, movedAmount / (double) bb);
}
public void signalFold(Propositionalizer p) {
lastActionWasRaise = false;
gameStats.addFold(p);
globalStats.addFold(p);
}
public void signalBlind(int amount) {
bet = amount;
decreaseStack(amount);
comitted = true;
}
public void signalFlop() {
++flopCount;
}
public void signalShowdown() {
++showdownCount;
}
public void resetStack(int stack) {
this.stack = stack;
if (stack < 0) {
throw new IllegalStateException("Bad stack: " + stack);
}
}
@Override
public String toString() {
return "PlayerData " + Long.toHexString(hashCode()) + " for " + id.toString();
}
}