|
|
|
@ -3,6 +3,7 @@ package net.pokeranalytics.android.model.handhistory |
|
|
|
import net.pokeranalytics.android.exceptions.PAIllegalStateException |
|
|
|
import net.pokeranalytics.android.exceptions.PAIllegalStateException |
|
|
|
import net.pokeranalytics.android.model.realm.handhistory.Action |
|
|
|
import net.pokeranalytics.android.model.realm.handhistory.Action |
|
|
|
import net.pokeranalytics.android.model.realm.handhistory.HandHistory |
|
|
|
import net.pokeranalytics.android.model.realm.handhistory.HandHistory |
|
|
|
|
|
|
|
import kotlin.math.min |
|
|
|
|
|
|
|
|
|
|
|
class Builder { |
|
|
|
class Builder { |
|
|
|
|
|
|
|
|
|
|
|
@ -23,10 +24,10 @@ class Builder { |
|
|
|
/*** |
|
|
|
/*** |
|
|
|
* All actions sorted by index |
|
|
|
* All actions sorted by index |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
private val sortedActions: List<ComputedAction> |
|
|
|
private var sortedActions: List<ComputedAction> = listOf() |
|
|
|
get() { |
|
|
|
// get() { |
|
|
|
return actionsPerStreet.flatMap { it.value } |
|
|
|
// return actionsPerStreet.flatMap { it.value } |
|
|
|
} |
|
|
|
// } |
|
|
|
|
|
|
|
|
|
|
|
/*** |
|
|
|
/*** |
|
|
|
* Creates a builder using a [handSetup] |
|
|
|
* Creates a builder using a [handSetup] |
|
|
|
@ -52,7 +53,7 @@ class Builder { |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
private fun load() { |
|
|
|
private fun load() { |
|
|
|
|
|
|
|
|
|
|
|
var potSize = 0.0 |
|
|
|
// var potSize = 0.0 |
|
|
|
var totalPotSize = 0.0 |
|
|
|
var totalPotSize = 0.0 |
|
|
|
|
|
|
|
|
|
|
|
// on veut sortir: |
|
|
|
// on veut sortir: |
|
|
|
@ -61,16 +62,24 @@ class Builder { |
|
|
|
// => ne pas oublier flop / turn / river / résumé |
|
|
|
// => ne pas oublier flop / turn / river / résumé |
|
|
|
|
|
|
|
|
|
|
|
// sorted actions |
|
|
|
// sorted actions |
|
|
|
|
|
|
|
val computedActions = mutableListOf<ComputedAction>() |
|
|
|
val sortedActions = this.handHistory.actions.sortedBy { it.index } |
|
|
|
val sortedActions = this.handHistory.actions.sortedBy { it.index } |
|
|
|
Street.values().forEach { street -> |
|
|
|
sortedActions.forEach { action -> |
|
|
|
val filteredActions = sortedActions.filter { it.street == street.ordinal } |
|
|
|
|
|
|
|
val computedActions = filteredActions.map { action -> |
|
|
|
|
|
|
|
totalPotSize += action.effectiveAmount |
|
|
|
totalPotSize += action.effectiveAmount |
|
|
|
ComputedAction(action, potSize, totalPotSize, action.positionRemainingStack) |
|
|
|
val ca = ComputedAction(action, totalPotSize, action.positionRemainingStack) |
|
|
|
} |
|
|
|
computedActions.add(ca) |
|
|
|
this.actionsPerStreet[street] = computedActions |
|
|
|
|
|
|
|
potSize = totalPotSize |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
this.sortedActions = computedActions |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Street.values().forEach { street -> |
|
|
|
|
|
|
|
// val filteredActions = sortedActions.filter { it.street == street.ordinal } |
|
|
|
|
|
|
|
// val computedActions = filteredActions.map { action -> |
|
|
|
|
|
|
|
// totalPotSize += action.effectiveAmount |
|
|
|
|
|
|
|
// ComputedAction(action, potSize, totalPotSize, action.positionRemainingStack) |
|
|
|
|
|
|
|
// } |
|
|
|
|
|
|
|
// this.actionsPerStreet[street] = computedActions |
|
|
|
|
|
|
|
// potSize = totalPotSize |
|
|
|
|
|
|
|
// } |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/*** |
|
|
|
/*** |
|
|
|
@ -88,13 +97,13 @@ class Builder { |
|
|
|
|
|
|
|
|
|
|
|
when (lastSignificantAction.action.type) { |
|
|
|
when (lastSignificantAction.action.type) { |
|
|
|
Action.Type.POST_BB, Action.Type.STRADDLE -> { |
|
|
|
Action.Type.POST_BB, Action.Type.STRADDLE -> { |
|
|
|
setOf(Action.Type.STRADDLE, Action.Type.FOLD, Action.Type.CALL, Action.Type.BET, Action.Type.BET_ALLIN) |
|
|
|
setOf(Action.Type.STRADDLE, Action.Type.FOLD, Action.Type.CALL, Action.Type.BET, Action.Type.UNDEFINED_ALLIN) |
|
|
|
} |
|
|
|
} |
|
|
|
Action.Type.BET, Action.Type.RAISE -> { |
|
|
|
Action.Type.BET, Action.Type.RAISE -> { |
|
|
|
if (remainingStack != null && actionAmount != null && remainingStack <= actionAmount) { |
|
|
|
if (remainingStack != null && actionAmount != null && remainingStack <= actionAmount) { |
|
|
|
setOf(Action.Type.FOLD, Action.Type.CALL_ALLIN) |
|
|
|
setOf(Action.Type.FOLD, Action.Type.CALL_ALLIN) |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
setOf(Action.Type.FOLD, Action.Type.CALL, Action.Type.RAISE, Action.Type.RAISE_ALLIN) |
|
|
|
setOf(Action.Type.FOLD, Action.Type.CALL, Action.Type.RAISE, Action.Type.UNDEFINED_ALLIN) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
Action.Type.RAISE_ALLIN, Action.Type.BET_ALLIN -> { |
|
|
|
Action.Type.RAISE_ALLIN, Action.Type.BET_ALLIN -> { |
|
|
|
@ -103,7 +112,7 @@ class Builder { |
|
|
|
} else if (this.remainingPlayerCount(index) == 2 && remainingStack != null && actionAmount != null && remainingStack > actionAmount) { |
|
|
|
} else if (this.remainingPlayerCount(index) == 2 && remainingStack != null && actionAmount != null && remainingStack > actionAmount) { |
|
|
|
setOf(Action.Type.FOLD, Action.Type.CALL) |
|
|
|
setOf(Action.Type.FOLD, Action.Type.CALL) |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
setOf(Action.Type.FOLD, Action.Type.CALL, Action.Type.RAISE, Action.Type.RAISE_ALLIN) |
|
|
|
setOf(Action.Type.FOLD, Action.Type.CALL, Action.Type.RAISE, Action.Type.UNDEFINED_ALLIN) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
else -> { |
|
|
|
else -> { |
|
|
|
@ -129,15 +138,90 @@ class Builder { |
|
|
|
* If the user changes the current action, |
|
|
|
* If the user changes the current action, |
|
|
|
* for convenience we remove all the following actions to avoid managing complex cases |
|
|
|
* for convenience we remove all the following actions to avoid managing complex cases |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
private fun selectAction(index: Int, actionType: Action.Type) { |
|
|
|
private fun selectAction(index: Int, actionType: Action.Type) : Boolean { |
|
|
|
// if the selected action is different from current, remove any action after the index |
|
|
|
// if the selected action is different from current, remove any action after the index |
|
|
|
|
|
|
|
val computedAction = this.sortedActions.first { it.action.index == index } |
|
|
|
|
|
|
|
computedAction.action.type = actionType |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
dropIfNecessary(index) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// remaining stack + effective amount |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
when (actionType) { |
|
|
|
|
|
|
|
Action.Type.CALL -> { |
|
|
|
|
|
|
|
val significantAmount = getLastSignificantAction(index)?.action?.amount ?: throw PAIllegalStateException("Cannot happen") |
|
|
|
|
|
|
|
val committedAmount = getPreviousCommittedAmount(index) ?: 0.0 |
|
|
|
|
|
|
|
computedAction.setEffectiveAmount(significantAmount - committedAmount) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
Action.Type.CALL_ALLIN -> { |
|
|
|
|
|
|
|
computedAction.setEffectiveAmount(computedAction.playerRemainingStack!!) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
Action.Type.STRADDLE -> { |
|
|
|
|
|
|
|
// TODO |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return computedAction.requireAmount |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private fun dropIfNecessary(index: Int) { |
|
|
|
|
|
|
|
this.sortedActions.drop(index + 1) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/*** |
|
|
|
/*** |
|
|
|
* Sets the amount for the action at the provided [index] |
|
|
|
* Sets the amount for the action at the provided [index] |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
private fun setAmount(index: Int, amount: Double) { |
|
|
|
private fun setAmount(index: Int, amount: Double) { |
|
|
|
|
|
|
|
val computedAction = this.sortedActions.first { it.action.index == index } |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
val adjustedAmount = computedAction.playerRemainingStack?.let { min(it, amount) } ?: amount |
|
|
|
|
|
|
|
computedAction.action.amount = adjustedAmount |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
when (computedAction.action.type) { |
|
|
|
|
|
|
|
Action.Type.UNDEFINED_ALLIN -> { |
|
|
|
|
|
|
|
getLastSignificantAction(index)?.action?.amount?.let { significantActionAmount -> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
val committedAmount = getPreviousCommittedAmount(index) ?: 0.0 |
|
|
|
|
|
|
|
val askedAmount = significantActionAmount - committedAmount |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
computedAction.playerRemainingStack?.let { remainingStack -> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (remainingStack > askedAmount) { |
|
|
|
|
|
|
|
selectAction(index, Action.Type.RAISE_ALLIN) |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
selectAction(index, Action.Type.CALL_ALLIN) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} ?: run { |
|
|
|
|
|
|
|
selectAction(index, Action.Type.RAISE_ALLIN) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} ?: run { |
|
|
|
|
|
|
|
selectAction(index, Action.Type.RAISE_ALLIN) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else -> {} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private fun getPreviousCommittedAmount(index: Int) : Double? { |
|
|
|
|
|
|
|
val computedAction = this.sortedActions.first { it.action.index == index } |
|
|
|
|
|
|
|
val position = computedAction.action.position |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
val previousActions = this.sortedActions.drop(index) |
|
|
|
|
|
|
|
val previousComputedAction = previousActions.lastOrNull { it.action.position == position } |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
previousComputedAction?.action?.let { action -> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return when (action.type) { |
|
|
|
|
|
|
|
Action.Type.POST_BB, Action.Type.POST_SB, Action.Type.STRADDLE, Action.Type.BET, Action.Type.RAISE -> action.amount |
|
|
|
|
|
|
|
Action.Type.CALL -> getLastSignificantAction(action.index)?.action?.amount |
|
|
|
|
|
|
|
else -> null |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return null |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/*** |
|
|
|
/*** |
|
|
|
|