package bots.smarterbot;
import com.biotools.meerkat.Card;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Scanner;
public class History {
private static final String POKER_HISTORY_FILE = "./data/PokerHistory.dat";
private class HandHistory {
public HandHistory() {
count = new int[6];
profit = new double[6];
for (int i = 0; i < 6; i++) {
count[i] = 0;
profit[i] = 0;
}
}
private int count[];
private double profit[];
}
private HandHistory history[][];
public History() {
history = new HandHistory[13][13];
for (int i = 0; i < 13; i++) {
for (int j = 0; j < 13; j++) {
history[i][j] = new HandHistory();
}
}
readFile(); // attempt to read data from an existing file. On failure, do nothing
}
/**
* Returns an action that should replace the old action in the playmatrix
*
* @param c1 is the first card in players hand
* @param c2 is the second card in players hand
* @param profit is how much gain was made in the hand
* @param rank is what preflop level the hand was played at
*/
public Action update(Card c1, Card c2, double profit, int rank, int curRank) {
double thisProfit = 0, upProfit = 0, downProfit = 0;
boolean upValid = false, downValid = false;
HandHistory history;
if ((c1.getSuit() == c2.getSuit()) == (c1.getRank() <= c2.getRank())) {
history = this.history[c1.getRank()][c2.getRank()];
} else {
history = this.history[c2.getRank()][c1.getRank()];
}
history.count[rank]++;
history.profit[rank] += profit;
//begin code for recommending a hand level
if (history.count[curRank] >= 4) { //we have at least 4 tests done at current hypothesized level
thisProfit = history.profit[curRank] / history.count[curRank];
if (curRank < 5 && history.count[curRank + 1] >= 3) {
upProfit = history.profit[curRank + 1] / history.count[curRank + 1];
upValid = true;
}
if (curRank > 0 && history.count[curRank - 1] >= 3) {
downProfit = history.profit[curRank - 1] / history.count[curRank - 1];
downValid = true;
}
if (upValid && upProfit < thisProfit) {
upValid = false;
}
if (downValid && downProfit < thisProfit) {
downValid = false;
}
if (upValid && downValid) {
if (upProfit >= downProfit && history.count[curRank + 1] >= history.count[curRank - 1]) {
return Action.convert(curRank + 1);
} else if (upProfit <= downProfit && history.count[curRank + 1] <= history.count[curRank - 1]) {
return Action.convert(curRank - 1);
} else { // simple weighting for confidence interval (I fail at statistics basically)
upProfit -= Math.abs(upProfit / (history.count[curRank + 1] * 4));
downProfit -= Math.abs(downProfit / (history.count[curRank - 1] * 4));
if (upProfit >= downProfit) {
return Action.convert(curRank + 1);
} else {
return Action.convert(curRank - 1);
}
}
} else if (upValid) {
return Action.convert(curRank + 1);
} else if (downValid) {
return Action.convert(curRank - 1);
}
}
return Action.INVALID;
}
public Action getNeeded(Card c1, Card c2, Action levelAction) {
int order1, order2;
int level = levelAction.getValue();
if ((c1.getSuit() == c2.getSuit()) == (c1.getRank() <= c2.getRank())) {
order1 = c1.getRank();
order2 = c2.getRank();
} else {
order1 = c2.getRank();
order2 = c1.getRank();
}
if (history[order1][order2].count[level] < 4) {
if ((level > 0 && history[order1][order2].count[level - 1] > 3) || (level < 5 && history[order1][order2].count[level + 1] > 3)) {
return levelAction;
}
return Action.INVALID;
}
if (level < 5) {
if (history[order1][order2].count[level + 1] < 3) {
return levelAction.oneUp();
}
}
if (level > 0) {
if (history[order1][order2].count[level - 1] < 3) {
return levelAction.oneDown();
}
}
return Action.INVALID;
}
public boolean writeFile() {
FileWriter writer;
try {
writer = new FileWriter(POKER_HISTORY_FILE, false);
} catch (IOException e) {
return false;
}
for (int i = 0; i < 13; i++) {
for (int j = 0; j < 13; j++) {
for (int k = 0; k < 6; k++) {
try {
writer.write(history[i][j].count[k] + " " + history[i][j].profit[k] + " ");
} catch (IOException error) {
try {
writer.close();
return false;
} catch (IOException e) {
return false;
}
}
}
}
}
try {
writer.close();
} catch (IOException e) {
}
return true;
}
public boolean readFile() { // overrides present data with data from file
Scanner writer;
HandHistory history[][] = new HandHistory[13][13];
for (int i = 0; i < 13; i++) {
for (int j = 0; j < 13; j++) {
history[i][j] = new HandHistory();
}
}
try {
writer = new Scanner(new File(POKER_HISTORY_FILE));
} catch (IOException e) {
return false;
}
writer.useDelimiter(" ");
for (int i = 0; i < 13; i++) {
for (int j = 0; j < 13; j++) {
for (int k = 0; k < 6; k++) {
if (!writer.hasNextInt()) {
return false;
}
history[i][j].count[k] = writer.nextInt();
if (!writer.hasNextDouble()) {
return false;
}
history[i][j].profit[k] = writer.nextDouble();
}
}
}
this.history = history;
return true;
}
}