package com.hearthsim.gui;
import com.hearthsim.event.HSGameEndEventListener;
import com.hearthsim.player.playercontroller.BruteForceSearchAI;
import com.hearthsim.results.GameResult;
import org.apache.commons.math3.distribution.BetaDistribution;
import java.util.ArrayList;
import java.util.Observable;
public class HSMainFrameModel implements HSGameEndEventListener {
private final HearthSim view_;
private final HSSimulation simulation_;
private boolean isRunning_;
// Game result statistics
final GameStats gameStats_;
public class GameStats {
ArrayList<GameResult> gameResults_;
int p0_wins_;
int p1_wins_;
int[] p0_numMinionsOnTurn_;
int[] p1_numMinionsOnTurn_;
int[] p0_numCardsOnTurn_;
int[] p1_numCardsOnTurn_;
int[] p0_heroHealthOnTurn_;
int[] p1_heroHealthOnTurn_;
int p0_wins_fst_;
int p0_fst_;
int p1_wins_fst_;
int p1_fst_;
public GameStats() {
gameResults_ = new ArrayList<>();
p0_numMinionsOnTurn_ = new int[50];
p1_numMinionsOnTurn_ = new int[50];
p0_numCardsOnTurn_ = new int[50];
p1_numCardsOnTurn_ = new int[50];
p0_heroHealthOnTurn_ = new int[50];
p1_heroHealthOnTurn_ = new int[50];
}
public synchronized void add(GameResult result) {
gameResults_.add(result);
if (result.winnerPlayerIndex_ == 0)
++p0_wins_;
else if (result.winnerPlayerIndex_ == 1)
++p1_wins_;
if (result.firstPlayerIndex_ == 0) {
++p0_fst_;
if (result.winnerPlayerIndex_ == 0)
++p0_wins_fst_;
} else if (result.firstPlayerIndex_ == 1) {
++p1_fst_;
if (result.winnerPlayerIndex_ == 1)
++p1_wins_fst_;
}
int nR_0 = result.record_.getRecordLength(0);
if (nR_0 > 50)
nR_0 = 50;
int nR_1 = result.record_.getRecordLength(1);
if (nR_1 > 50)
nR_1 = 50;
for (int indx = 0; indx < nR_0; ++indx) {
p0_numMinionsOnTurn_[indx] += result.record_.getNumMinions(0,
indx, 0);
}
for (int indx = 0; indx < nR_1; ++indx) {
p1_numMinionsOnTurn_[indx] += result.record_.getNumMinions(1,
indx, 1);
}
for (int indx = 0; indx < nR_0; ++indx) {
p0_numCardsOnTurn_[indx] += result.record_.getNumCardsInHand(0,
indx, 0);
}
for (int indx = 0; indx < nR_1; ++indx) {
p1_numCardsOnTurn_[indx] += result.record_.getNumCardsInHand(1,
indx, 1);
}
for (int indx = 0; indx < nR_0; ++indx) {
p0_heroHealthOnTurn_[indx] += result.record_.getHeroHealth(0,
indx, 0);
}
for (int indx = 0; indx < nR_1; ++indx) {
p1_heroHealthOnTurn_[indx] += result.record_.getHeroHealth(1,
indx, 1);
}
}
void reset() {
p0_wins_ = 0;
p1_wins_ = 0;
p0_wins_fst_ = 0;
p0_fst_ = 0;
p1_wins_fst_ = 0;
p1_fst_ = 0;
gameResults_ = new ArrayList<>();
p0_numMinionsOnTurn_ = new int[50];
p1_numMinionsOnTurn_ = new int[50];
p0_numCardsOnTurn_ = new int[50];
p1_numCardsOnTurn_ = new int[50];
p0_heroHealthOnTurn_ = new int[50];
p1_heroHealthOnTurn_ = new int[50];
}
int getWins_p0() {
return p0_wins_;
}
int getWins_p1() {
return p1_wins_;
}
double getWinRate_p0() {
if (p0_wins_ + p1_wins_ == 0)
return 0.0;
return p0_wins_ / ((double) p0_wins_ + (double) p1_wins_);
}
double getWinRate_p1() {
if (p0_wins_ + p1_wins_ == 0)
return 0.0;
return p1_wins_ / ((double) p0_wins_ + (double) p1_wins_);
}
double getWinRateWhenGoingFirst_p0() {
if (p0_fst_ == 0)
return 0.0;
return (double) p0_wins_fst_ / ((double) p0_fst_);
}
double getWinRateWhenGoingFirst_p1() {
if (p1_fst_ == 0)
return 0.0;
return (double) p1_wins_fst_ / ((double) p1_fst_);
}
double getWinRateContRange_lower(double confPercent, int winCount,
int totalNumGames) {
BetaDistribution beta = new BetaDistribution(winCount,
totalNumGames - winCount + 1);
return beta.inverseCumulativeProbability((1.0 - confPercent) * 0.5);
}
double getWinRateContRange_upper(double confPercent, int winCount,
int totalNumGames) {
BetaDistribution beta = new BetaDistribution(winCount + 1,
totalNumGames - winCount);
return beta
.inverseCumulativeProbability(1.0 - (1.0 - confPercent) * 0.5);
}
double[] getAveNumMinions_p0() {
int nGames = gameResults_.size();
double[] toRet = new double[50];
for (int indx = 0; indx < 50; ++indx) {
toRet[indx] = (double) p0_numMinionsOnTurn_[indx]
/ (double) nGames;
}
return toRet;
}
double[] getAveNumMinions_p1() {
int nGames = gameResults_.size();
double[] toRet = new double[50];
for (int indx = 0; indx < 50; ++indx) {
toRet[indx] = (double) p1_numMinionsOnTurn_[indx]
/ (double) nGames;
}
return toRet;
}
double[] getAveNumCards_p0() {
int nGames = gameResults_.size();
double[] toRet = new double[50];
for (int indx = 0; indx < 50; ++indx) {
toRet[indx] = (double) p0_numCardsOnTurn_[indx]
/ (double) nGames;
}
return toRet;
}
double[] getAveNumCards_p1() {
int nGames = gameResults_.size();
double[] toRet = new double[50];
for (int indx = 0; indx < 50; ++indx) {
toRet[indx] = (double) p1_numCardsOnTurn_[indx]
/ (double) nGames;
}
return toRet;
}
double[] getAveHeroHealth_p0() {
int nGames = gameResults_.size();
double[] toRet = new double[50];
for (int indx = 0; indx < 50; ++indx) {
toRet[indx] = (double) p0_heroHealthOnTurn_[indx]
/ (double) nGames;
}
return toRet;
}
double[] getAveHeroHealth_p1() {
int nGames = gameResults_.size();
double[] toRet = new double[50];
for (int indx = 0; indx < 50; ++indx) {
toRet[indx] = (double) p1_heroHealthOnTurn_[indx]
/ (double) nGames;
}
return toRet;
}
}
public HSMainFrameModel(HearthSim view) {
view_ = view;
simulation_ = new HSSimulation(this);
gameStats_ = new GameStats();
simulation_.getConfig().numSimulations_ = 10;
simulation_.getConfig().numThreads_ = 1;
simulation_.getConfig().simName_ = "HearthSim";
simulation_.setAI_p0(BruteForceSearchAI.buildStandardAI2());
simulation_.setAI_p1(BruteForceSearchAI.buildStandardAI2());
}
public HSSimulation getSimulation() {
return simulation_;
}
public GameStats getGameStats() {
return gameStats_;
}
@Override
public synchronized void gameEnded(GameResult result) {
gameStats_.add(result);
view_.updatePlotPanel();
view_.updateInfoPanel();
}
public boolean isRunning() {
return this.isRunning_;
}
public void runSimulation() {
simulation_.run();
isRunning_ = true;
}
public void stopSimulation() {
simulation_.stop();
isRunning_ = false;
}
public void resetSimulationResults() {
gameStats_.reset();
}
@Override
public void update(Observable o, Object arg) {
gameEnded((GameResult) arg);
}
}