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 9d8a631b..e442b053 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 @@ -9,6 +9,7 @@ import net.pokeranalytics.android.ui.modules.handhistory.model.ActionReadRow import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.RowViewType import net.pokeranalytics.android.util.extensions.formatted +import timber.log.Timber /*** @@ -172,6 +173,10 @@ open class Action : RealmObject() { * The amount linked for a bet, raise... */ var amount: Double? = null + set(value) { + field = value + Timber.d("/// set value = $value") + } var effectiveAmount: Double = 0.0 @@ -184,7 +189,7 @@ open class Action : RealmObject() { val formattedAmount: String? get() { - val amount = when (type) { + val amount = when (this.type) { Type.CALL, Type.CALL_ALLIN -> this.effectiveAmount else -> this.amount } 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 6bcd271a..07bd8be6 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 @@ -84,7 +84,9 @@ open class HandHistory : RealmObject(), Deletable, RowRepresentable, Filterable, var ante: Double = 0.0 set(value) { field = value - this.bigBlindAnte = false + if (this.bigBlindAnte) { + this.bigBlindAnte = false + } } /*** @@ -93,7 +95,9 @@ open class HandHistory : RealmObject(), Deletable, RowRepresentable, Filterable, var bigBlindAnte: Boolean = false set(value) { field = value - this.ante = 0.0 + if (this.ante > 0) { + this.ante = 0.0 + } } /*** @@ -153,6 +157,8 @@ open class HandHistory : RealmObject(), Deletable, RowRepresentable, Filterable, */ fun configure(handSetup: HandSetup) { + this.playerSetups.removeAll(this.playerSetups) + handSetup.tableSize?.let { this.numberOfPlayers = it } handSetup.smallBlind?.let { this.smallBlind = it } handSetup.bigBlind?.let { this.bigBlind = it } @@ -201,6 +207,7 @@ open class HandHistory : RealmObject(), Deletable, RowRepresentable, Filterable, action.position = position action.type = type action.amount = amount + action.effectiveAmount = amount ?: 0.0 this.actions.add(action) } @@ -350,6 +357,18 @@ open class HandHistory : RealmObject(), Deletable, RowRepresentable, Filterable, return string } + fun anteForPosition(position: Position): Double { + return if (this.bigBlindAnte) { + if (position == Position.BB) { + this.bigBlind ?: 0.0 + } else { + 0.0 + } + } else { + this.ante + } + } + /*** * Returns a string representation of the [playerSetup] */ diff --git a/app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/model/ActionList.kt b/app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/model/ActionList.kt index 263baf01..b4900af3 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/model/ActionList.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/model/ActionList.kt @@ -18,6 +18,9 @@ interface ActionManager { fun blindsUpdated(type: Action.Type, amount: Double) fun minimumBetAmount(index: Int): Double fun totalPotSize(index: Int): Double + fun initialStack(position: Int): Double? + fun stackForNewAction(action: Action): Double? + fun stackAtStreetStart(index: Int): Double? val heroIndex: Int? } @@ -60,7 +63,6 @@ class ActionList(var listener: ActionListListener) : ArrayList() this, action, totalPotSize, - action.positionRemainingStack, position ) computedActions.add(ca) @@ -88,29 +90,8 @@ class ActionList(var listener: ActionListListener) : ArrayList() */ override fun selectAction(index: Int, actionType: Action.Type) { - var type = actionType val computedAction = this[index] - // define allin type - if (type == Action.Type.UNDEFINED_ALLIN) { - val significant = getStreetLastSignificantAction(computedAction.street, index - 1) - type = if (significant != null) { - val betAmount = significant.action.amount - val remainingStack = computedAction.playerRemainingStack - if (remainingStack != null && betAmount != null && remainingStack < betAmount) { - Action.Type.CALL_ALLIN - } else { - Action.Type.RAISE_ALLIN - } - } else { - Action.Type.BET_ALLIN - } - } - - Timber.d(">>> Sets $type at index: $index") - - computedAction.setType(type) // false - // Automatically sets action for the previous empty actions val modifiedActions = mutableListOf() getPreviousEmptyActions(index).forEach { @@ -123,7 +104,43 @@ class ActionList(var listener: ActionListListener) : ArrayList() } } + var type = actionType + + // define allin type + + when (type) { + Action.Type.UNDEFINED_ALLIN -> { + + val significant = getStreetLastSignificantAction(computedAction.street, index - 1) + type = if (significant != null) { + val betAmount = significant.action.amount + val remainingStack = computedAction.stackBeforeActing + if (remainingStack != null && betAmount != null && remainingStack < betAmount) { + Action.Type.CALL_ALLIN + } else { + Action.Type.RAISE_ALLIN + } + } else { + Action.Type.BET_ALLIN + } + + } + Action.Type.CALL -> { + getStreetLastSignificantAction(computedAction.street, index - 1)?.action?.amount?.let { betAmount -> + val remainingStack = computedAction.stackBeforeActing + if (remainingStack != null && remainingStack < betAmount) { + type = Action.Type.CALL_ALLIN + } + } ?: throw PAIllegalStateException("Can't happen") + } + else -> {} + } + Timber.d(">>> Sets $type at index: $index") + + computedAction.setType(type) + this.updateFollowupActions(index) + this.updateRemainingStacksForPositions(listOf(computedAction.action.position)) fireListener() } @@ -133,7 +150,8 @@ class ActionList(var listener: ActionListListener) : ArrayList() */ fun setAmount(index: Int, amount: Double) { val computedAction = this[index] - computedAction.setAmount(amount) + computedAction.setBetAmount(amount) + this.updateRemainingStacksForPositions(listOf(computedAction.action.position)) } /*** @@ -180,7 +198,7 @@ class ActionList(var listener: ActionListListener) : ArrayList() return if (lastSignificantAction == null) { setOf(Action.Type.FOLD, Action.Type.CHECK, Action.Type.BET, Action.Type.POT, Action.Type.UNDEFINED_ALLIN) } else { - val remainingStack = getLastPlayerAction(index)?.playerRemainingStack + val remainingStack = computedAction.stackBeforeActing val actionAmount = lastSignificantAction.action.amount when (lastSignificantAction.action.type) { @@ -273,15 +291,6 @@ class ActionList(var listener: ActionListListener) : ArrayList() return this.take(index).filter { it.street == street && it.action.type == null } } - /*** - * Returns the last user action, if any, for the action at the provided [index] - */ - private fun getLastPlayerAction(index: Int): ComputedAction? { - val action = this[index].action - val previousActions = this.take(index) - return previousActions.lastOrNull { it.positionIndex == action.position } - } - /*** * Returns the last significant player action, if any, for the action at the provided [index] */ @@ -319,7 +328,7 @@ class ActionList(var listener: ActionListListener) : ArrayList() activePositions.indexOfFirst { it.ordinal > refIndexPosition.ordinal }) for (i in 0 until activePositions.size) { val position = activePositions[(firstPositionAfterCurrent + i) % activePositions.size] - this.addNewEmptyAction(position, refAction.street, refAction.totalPotSize, lastRemainingStack(position, index)) + this.addNewEmptyAction(position, refAction.street, refAction.totalPotSize) } if (activePositions.isNotEmpty()) { @@ -330,7 +339,7 @@ class ActionList(var listener: ActionListListener) : ArrayList() /*** * Creates a new action at the end of the action stack, and in the HH representation */ - private fun addNewEmptyAction(position: Position, street: Street, currentPotSize: Double, remainingStack: Double?) { + private fun addNewEmptyAction(position: Position, street: Street, currentPotSize: Double) { if (street == Street.SUMMARY) { throw PAIllegalStateException("Summary cannot have player actions") @@ -345,7 +354,6 @@ class ActionList(var listener: ActionListListener) : ArrayList() this, action, currentPotSize, - remainingStack, position ) this.add(computedAction) @@ -353,13 +361,6 @@ class ActionList(var listener: ActionListListener) : ArrayList() this.sizeChanged = true } - /*** - * Returns the last remaining stack of the player, if available - */ - private fun lastRemainingStack(position: Position, index: Int): Double? { - return this.take(index).lastOrNull { it.position == position }?.playerRemainingStack - } - /*** * Adds, if necessary, new ComputedAction for players that needs to act * Also adds, if necessary, the Street separators and board selectors @@ -481,7 +482,8 @@ class ActionList(var listener: ActionListListener) : ArrayList() created = true } - playerSetup.stack = this.filter { it.positionIndex == positionIndex }.sumByDouble { it.action.effectiveAmount } + val stack = this.filter { it.positionIndex == positionIndex }.sumByDouble { it.action.effectiveAmount } + playerSetup.stack = stack if (created) { this.listener.playerSetupCreated() @@ -497,7 +499,7 @@ class ActionList(var listener: ActionListListener) : ArrayList() Action.Type.POST_BB -> { this.handHistory.bigBlind = amount if (this.handHistory.bigBlindAnte) { - this.updateRemainingStacksForPositions(listOf()) + this.updateBigBlindRemainingStack() } } else -> throw PAIllegalStateException("Should never happen") @@ -586,7 +588,7 @@ class ActionList(var listener: ActionListListener) : ArrayList() val lastActionIndex = lastComputedAction.action.index val isShowDown = street == Street.SUMMARY activePositions(lastActionIndex, isShowDown).sortedBy { it.ordinal }.forEach { - addNewEmptyAction(it, street, totalPotSize, lastRemainingStack(it, lastActionIndex)) + addNewEmptyAction(it, street, totalPotSize) } } @@ -608,23 +610,26 @@ class ActionList(var listener: ActionListListener) : ArrayList() } /*** - * Recomputes all remaining stacks for the given [positionIndexes] + * Recomputes all remaining stacks for the given [positionIndexes], after the given [index] */ fun updateRemainingStacksForPositions(positionIndexes: List) { - val ante = if (this.handHistory.bigBlindAnte) this.handHistory.bigBlind ?: 0.0 else this.handHistory.ante - positionIndexes.forEach { posIndex -> + val ante = this.handHistory.anteForPosition(this.positions.elementAt(posIndex)) + this.handHistory.playerSetupForPosition(posIndex)?.stack?.let { initialStack -> - var remainingStack = initialStack - ante + val startStack = initialStack - ante val playerActions = this.filter { it.positionIndex == posIndex } + + var previousAction: ComputedAction? = null playerActions.forEach { - remainingStack -= it.action.effectiveAmount - it.playerRemainingStack = remainingStack +// remainingStack -= it.action.effectiveAmount + it.stackBeforeActing = previousAction?.stackAfterActing ?: startStack if (it.action.type?.isAllin == true) { - it.action.amount = remainingStack + it.action.amount = this.stackAtStreetStart(it.action.index) } + previousAction = it } } @@ -632,30 +637,22 @@ class ActionList(var listener: ActionListListener) : ArrayList() } - /*** - * Updates all ComputedAction linked to the position with an updated value of the remaining stack - */ - fun stackUpdatedAtPosition(positionIndex: Int) { - this.handHistory.playerSetupForPosition(positionIndex)?.let { playerSetup -> - - var remainingStack = playerSetup.stack - this.filter { it.action.position == positionIndex }.forEach { ca -> - - remainingStack?.let { rs -> - - if (ca.action.type?.isAllin == true) { // updates the action amount - ca.setType(ca.action.type!!) - } else { // updates the remaining stack - remainingStack = rs - ca.action.effectiveAmount - ca.playerRemainingStack = remainingStack - } + override fun initialStack(position: Int): Double? { + val ante = this.handHistory.anteForPosition(this.positions.elementAt(position)) + return this.handHistory.playerSetupForPosition(position)?.stack?.let { it - ante } ?: run { null} + } - } ?: run { - ca.playerRemainingStack = null - } + override fun stackForNewAction(action: Action): Double? { + return this.lastOrNull { it.action.position == action.position }?.stackAfterActing + ?: run { + this.initialStack(action.position) } + } - } ?: throw PAIllegalStateException("Can't happen") + override fun stackAtStreetStart(index: Int): Double? { + val computedAction = this[index] + val firstStreetAction = this.firstOrNull { it.street == computedAction.street && it.action.position == computedAction.action.position } + return firstStreetAction?.stackBeforeActing } } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/model/ComputedAction.kt b/app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/model/ComputedAction.kt index 32a263b7..2747e6e4 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/model/ComputedAction.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/model/ComputedAction.kt @@ -8,7 +8,6 @@ import net.pokeranalytics.android.model.realm.handhistory.HandHistory import net.pokeranalytics.android.model.realm.handhistory.toReadRow import net.pokeranalytics.android.ui.modules.handhistory.HandRowType import kotlin.math.max -import kotlin.math.min /*** * An extension to transform a list of ComputedAction into @@ -33,10 +32,27 @@ fun List.compact(positions: LinkedHashSet, heroIndex: class ComputedAction(var manager: ActionManager, var action: Action, var totalPotSize: Double = 0.0, - var playerRemainingStack: Double? = null, var position: Position ) : HandHistoryRow, PositionalRow { + /*** + * The remaining stack before acting + */ + var stackBeforeActing: Double? = null + + init { + this.stackBeforeActing = this.manager.stackForNewAction(this.action) + } + + val stackAfterActing: Double? + get() { + return this.stackBeforeActing?.let { + it - this.action.effectiveAmount + } ?: run { + null + } + } + enum class Tag { PLAYER, ACTION, @@ -56,7 +72,7 @@ class ComputedAction(var manager: ActionManager, return when(this.action.type) { Action.Type.POST_SB, Action.Type.POST_BB, Action.Type.STRADDLE, Action.Type.BET, Action.Type.RAISE -> (this.action.amount == null) - Action.Type.BET_ALLIN, Action.Type.RAISE_ALLIN -> (this.playerRemainingStack == null && this.action.amount == null) + Action.Type.BET_ALLIN, Action.Type.RAISE_ALLIN -> (this.stackBeforeActing == null && this.action.amount == null) else -> false } } @@ -71,6 +87,7 @@ class ComputedAction(var manager: ActionManager, if (typeChange) { this.action.type = type this.action.amount = null + this.action.effectiveAmount = 0.0 } // define action amounts if possible @@ -79,21 +96,22 @@ class ComputedAction(var manager: ActionManager, updateEffectiveAmount() } Action.Type.CALL_ALLIN -> { - this.setEffectiveAmount(this.playerRemainingStack!!) - } - Action.Type.STRADDLE -> { - // TODO + this.action.effectiveAmount = this.stackBeforeActing!! } Action.Type.POT -> { val lastSignificantAction = this.getStreetLastSignificantAction() val lastSignificantAmount = lastSignificantAction?.action?.amount ?: 0.0 val potAmount = lastSignificantAmount * 2 + this.manager.totalPotSize(this.action.index) - this.setAmount(potAmount) + this.setBetAmount(potAmount) } Action.Type.BET_ALLIN, Action.Type.RAISE_ALLIN, Action.Type.UNDEFINED_ALLIN -> { - this.playerRemainingStack?.let { - this.setAmount(it) + this.manager.stackAtStreetStart(this.action.index)?.let { stack -> + this.setBetAmount(stack) } + +// this.stackBeforeActing?.let { +// this.setBetAmount(it) +// } } else -> {} } @@ -107,7 +125,7 @@ class ComputedAction(var manager: ActionManager, /*** * Sets the action amount */ - fun setAmount(amount: Double) { + fun setBetAmount(amount: Double) { if (amount <= 0) { return @@ -120,17 +138,9 @@ class ComputedAction(var manager: ActionManager, this.action.effectiveAmount = correctedAmount - committedAmount val oldAmount = this.action.amount - val remainingStack = this.playerRemainingStack + val remainingStack = this.stackBeforeActing if (oldAmount != null && remainingStack != null) { - - // Updates the remaining stack if the amount is changed - val oldPlayerRemainingStack = remainingStack + oldAmount - val revisedAmount = min(correctedAmount, oldPlayerRemainingStack) - val revisedRemainingStack = remainingStack - revisedAmount + oldAmount - this.playerRemainingStack = revisedRemainingStack - this.action.toggleType(remainingStack) - } else { this.action.amount = correctedAmount } @@ -154,7 +164,7 @@ class ComputedAction(var manager: ActionManager, this.getStreetLastSignificantAction()?.action?.amount?.let { significantActionAmount -> val askedAmount = significantActionAmount - committedAmount - this.playerRemainingStack?.let { remainingStack -> + this.stackBeforeActing?.let { remainingStack -> if (remainingStack < askedAmount) { this.manager.selectAction(this.action.index, Action.Type.CALL_ALLIN) } @@ -180,22 +190,22 @@ class ComputedAction(var manager: ActionManager, * Sets the effective amount of the action * Also calculates the player remaining stack if possible */ - private fun setEffectiveAmount(amount: Double) { - - val oldEffective = this.action.effectiveAmount - - this.action.effectiveAmount = amount - this.playerRemainingStack?.let { - - val oldPlayerRemainingStack = it + oldEffective - val revisedAmount = min(amount, oldPlayerRemainingStack) - val remainingStack = it - revisedAmount + oldEffective - this.playerRemainingStack = remainingStack - - this.action.toggleType(remainingStack) - - } - } +// private fun setEffectiveAmount(amount: Double) { +// this.action.effectiveAmount = amount +// +// val oldEffective = this.action.effectiveAmount +// +// this.stackBeforeActing?.let { +// +// val oldPlayerRemainingStack = it + oldEffective +// val revisedAmount = min(amount, oldPlayerRemainingStack) +// val remainingStack = it - revisedAmount + oldEffective +// this.stackBeforeActing = remainingStack +// +// this.action.toggleType(remainingStack) +// +// } +// } override fun isFieldNeedsInput(tag: Int, handHistory: HandHistory): Boolean { return when (tag) { @@ -236,19 +246,7 @@ class ComputedAction(var manager: ActionManager, val significantAmount = significantAction.action.amount ?: 0.0 val committedAmount = getPreviouslyCommittedAmount() - var effectiveAmount = significantAmount - committedAmount - - // Fixes effective if the remaining stack is lower - this.playerRemainingStack?.let { stack -> - if (stack < effectiveAmount) { - effectiveAmount = stack - if (this.action.type == Action.Type.CALL) { - this.action.type = Action.Type.CALL_ALLIN - } - } - } - - this.setEffectiveAmount(effectiveAmount) + this.action.effectiveAmount = significantAmount - committedAmount } private fun getStreetLastSignificantAction(): ComputedAction? { @@ -287,7 +285,7 @@ class ComputedAction(var manager: ActionManager, return when (this.action.type) { Action.Type.POST_SB, Action.Type.POST_BB, Action.Type.STRADDLE, Action.Type.BET, Action.Type.RAISE -> true - Action.Type.BET_ALLIN, Action.Type.RAISE_ALLIN -> (this.playerRemainingStack == null) + Action.Type.BET_ALLIN, Action.Type.RAISE_ALLIN -> true // (this.action.amount == null) else -> false } } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/model/HandHistoryViewModel.kt b/app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/model/HandHistoryViewModel.kt index 43f2a3f3..42297619 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/model/HandHistoryViewModel.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/modules/handhistory/model/HandHistoryViewModel.kt @@ -496,7 +496,7 @@ class HandHistoryViewModel : ViewModel(), RowRepresentableDataSource, CardCentra } is PlayerSetupRow -> { row.setStack(amount) - this.sortedActions.stackUpdatedAtPosition(row.positionIndex) + this.sortedActions.updateRemainingStacksForPositions(listOf(row.positionIndex)) } else -> {} }