diff --git a/app/src/main/java/net/pokeranalytics/android/model/handhistory/Builder.kt b/app/src/main/java/net/pokeranalytics/android/model/handhistory/Builder.kt index f3397d02..5e7962f5 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/handhistory/Builder.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/handhistory/Builder.kt @@ -3,6 +3,7 @@ package net.pokeranalytics.android.model.handhistory import net.pokeranalytics.android.exceptions.PAIllegalStateException import net.pokeranalytics.android.model.realm.handhistory.Action import net.pokeranalytics.android.model.realm.handhistory.HandHistory +import kotlin.math.min class Builder { @@ -23,10 +24,10 @@ class Builder { /*** * All actions sorted by index */ - private val sortedActions: List - get() { - return actionsPerStreet.flatMap { it.value } - } + private var sortedActions: List = listOf() +// get() { +// return actionsPerStreet.flatMap { it.value } +// } /*** * Creates a builder using a [handSetup] @@ -52,7 +53,7 @@ class Builder { */ private fun load() { - var potSize = 0.0 +// var potSize = 0.0 var totalPotSize = 0.0 // on veut sortir: @@ -61,16 +62,24 @@ class Builder { // => ne pas oublier flop / turn / river / résumé // sorted actions + val computedActions = mutableListOf() val sortedActions = this.handHistory.actions.sortedBy { it.index } - 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 + sortedActions.forEach { action -> + totalPotSize += action.effectiveAmount + val ca = ComputedAction(action, totalPotSize, action.positionRemainingStack) + computedActions.add(ca) } + 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) { 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 -> { if (remainingStack != null && actionAmount != null && remainingStack <= actionAmount) { setOf(Action.Type.FOLD, Action.Type.CALL_ALLIN) } 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 -> { @@ -103,7 +112,7 @@ class Builder { } else if (this.remainingPlayerCount(index) == 2 && remainingStack != null && actionAmount != null && remainingStack > actionAmount) { setOf(Action.Type.FOLD, Action.Type.CALL) } 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 -> { @@ -129,15 +138,90 @@ class Builder { * If the user changes the current action, * 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 + 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] */ 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 } /*** diff --git a/app/src/main/java/net/pokeranalytics/android/model/handhistory/ComputedAction.kt b/app/src/main/java/net/pokeranalytics/android/model/handhistory/ComputedAction.kt index 4620e052..7682b469 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/handhistory/ComputedAction.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/handhistory/ComputedAction.kt @@ -3,7 +3,6 @@ package net.pokeranalytics.android.model.handhistory import net.pokeranalytics.android.model.realm.handhistory.Action class ComputedAction(var action: Action, - var potSize: Double = 0.0, var totalPotSize: Double = 0.0, var playerRemainingStack: Double? = null) { @@ -16,4 +15,21 @@ class ComputedAction(var action: Action, // // var playerRemainingStack = 0.0 + + val requireAmount: Boolean + get() { + return when(this.action.type) { + Action.Type.BET, Action.Type.RAISE -> true + Action.Type.BET_ALLIN, Action.Type.RAISE_ALLIN -> (this.playerRemainingStack == null) + else -> false + } + } + + fun setEffectiveAmount(amount: Double) { + this.action.effectiveAmount = amount + this.playerRemainingStack?.let { + this.playerRemainingStack = it - amount + } + } + } \ No newline at end of file diff --git a/app/src/main/java/net/pokeranalytics/android/model/realm/handhistory/Action.kt b/app/src/main/java/net/pokeranalytics/android/model/realm/handhistory/Action.kt index 5f9d4ebc..30f056a6 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/realm/handhistory/Action.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/realm/handhistory/Action.kt @@ -1,6 +1,7 @@ package net.pokeranalytics.android.model.realm.handhistory import io.realm.RealmObject +import net.pokeranalytics.android.exceptions.PAIllegalStateException open class Action : RealmObject() { @@ -13,6 +14,7 @@ open class Action : RealmObject() { CALL, BET, RAISE, + UNDEFINED_ALLIN, CALL_ALLIN, BET_ALLIN, RAISE_ALLIN; @@ -21,9 +23,11 @@ open class Action : RealmObject() { get() { return when (this) { POST_BB, STRADDLE, BET, RAISE, BET_ALLIN, RAISE_ALLIN -> true + UNDEFINED_ALLIN -> throw PAIllegalStateException("Can't ask for UNDEFINED_ALLIN") else -> false } } + } /*** @@ -44,9 +48,12 @@ open class Action : RealmObject() { /*** * The type of action: check, fold, raise... */ - var typeIdentifier: Int? = null + private var typeIdentifier: Int? = null - val type: Type? + var type: Type? + set(value) { + this.typeIdentifier = value?.ordinal + } get() { return typeIdentifier?.let { Type.values()[it] } } @@ -57,7 +64,6 @@ open class Action : RealmObject() { var amount: Double? = null var effectiveAmount: Double = 0.0 - private set var positionRemainingStack: Double? = null diff --git a/app/src/main/java/net/pokeranalytics/android/model/realm/handhistory/HandHistory.kt b/app/src/main/java/net/pokeranalytics/android/model/realm/handhistory/HandHistory.kt index c1a79d74..6647bcbb 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/realm/handhistory/HandHistory.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/realm/handhistory/HandHistory.kt @@ -85,11 +85,11 @@ open class HandHistory : RealmObject() { action.position = i when (i) { 0 -> { - action.typeIdentifier = Action.Type.POST_SB.ordinal + action.type = Action.Type.POST_SB action.amount = this.smallBlind } 1 -> { - action.typeIdentifier = Action.Type.POST_BB.ordinal + action.type = Action.Type.POST_BB action.amount = this.bigBlind } else -> {